Python for模循环 [英] Python for loop with modulo
问题描述
是否可以通过模运算创建python for循环?我在Python中有一个环形缓冲区,我想迭代startPos
和endPos
索引之间的元素,其中startPos
的值可以比endPos
大.在其他编程语言中,我将使用模运算符直观地实现这一点:
Is it possible to create a python for-loop with a modulo operation? I have a ringbuffer in Python and I want to iterate the elements between the startPos
and endPos
indexes, where startPos
can have a bigger value than endPos
. In other programming languages, I would intuitively implement this with a modulo operator:
int startPos = 6;
int endPos = 2;
int ringBufferSize = 8;
for(int i = startPos, i != endPos, i = (i+1) % ringBufferSize) {
print buffer.getElementAt(i);
}
有没有一种方法可以在Python中轻松地做到这一点?我只找到了
Is there a way to do this easily in Python? I only found the
for i in list:
print buffer[i]
语法,但是什么也不能解决我的问题.
Syntax but nothing which provides an equivalent solution to my problem.
我的下一个方法是在迭代存储在列表中的索引之前预先创建列表.但是,有没有办法像在其他编程语言中那样通过在for循环中直接使用模运算来像单行代码一样做到这一点呢?
My next approach would be to create the list in advance before iterate the indexes which are stored in the list. But is there a way to do this as a one-liner like in other programming languages by using the modulo operation directly in the for loop?
推荐答案
您有一些方法可以做到这一点:
You have some ways of doing that:
就像您在其他编程语言"(即C派生的语法)中所做的一样,只是您基本上必须在一段时间内编写其for
循环-然后您才意识到C的for仍然是while
:
As you do in "other programing languages" (i.e. C derived syntaxes), just that you basically have to write their for
loop in a while form - and then you realize that C's for is just a while
nonetheless:
start_pos = 6
end_pos = 2
ring_buffer_size = 8
i = start_pos
while True:
i = (i + 1) % ring_buffer_size
if i <= end_pos:
break
# your code here
现在,对于for
语句,Python仅具有所谓的"for each"(始终),它总是遍历可迭代的或序列的.因此,您可以创建一个可迭代的变量,以产生您的值-
Now, for the for
statement, Python only has what is called "for each" - which always walks an iterable or sequence. So you can create an iterable that will yield your values -
def ring(start, end, buffer_size, increment=1):
i = start
while i != end:
yield i
i += 1
i %= buffer_size
for slot in ring(6, 2, 8):
# your code here
请注意,尽管第二种形式更大",但它确实抽象了循环缓冲区逻辑,避免了硬代码值与它们的含义混合在一起,而无需查看它们-即,在for
身体本身.
Note that while this second form is "bigger", it does abstract away your circular buffer logic, avoiding that hard code values get mixed with their meaning where you don't need to look at them - that is, inside the for
body itself.
请注意,Python中for
的实际想法是遍历 buffer 内容本身,而不是遍历将导致其内容的索引.
因此,Python标准库已经包含一个现成的循环缓冲区对象,该对象始终将其索引规范化为0和(len-1)-
只需从collections
模块导入deque
.
Note that the actual idea of for
in Python is to iterate over the buffer contents itself, not and index that will lead to its contents.
So, the Python standard library includes a ready made circular buffer object already that always have its indexes normalized to 0 and (len - 1) -
just import deque
from the collections
module.
如果您希望循环更改起始和结束索引的循环缓冲区taht可以在for
语句中环绕并自动工作,这也相对容易-如果您不需要全部功能,只需子类list
,添加start
和end
索引,并对其__iter__
方法进行自定义实现:
If you want a circular buffer with changing start and end indexes taht will wrap around and work automatically in for
statements, that is also relatively easy to do - if you don need the full functionality, just subclass list
, add the start
and end
indexes, and make a custom implementation of its __iter__
method:
class Circular(list):
def __init__(self, content, start, end):
super(Circular, self).__init__( content)
self.start = start
self.end = end
def __iter__(self):
for i in range(self.start, self.start + len(self)):
if i % len(self) == self.end: break
yield self[i % len(self)]
现在您可以在代码中使用此自定义容器:
And now you can use this custom container in your code:
In [22]: mylist = Circular(range(8), 6 , 2)
In [23]: for i in mylist:
...: print(i)
...:
6
7
0
1
这篇关于Python for模循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!