Python for 循环取模
Python for loop with modulo
是否可以使用模运算创建 python for 循环?我在 Python 中有一个环形缓冲区,我想迭代 startPos
和 endPos
索引之间的元素,其中 startPos
的值可以大于 endPos
。在其他编程语言中,我会直观地使用模运算符来实现它:
int startPos = 6;
int endPos = 2;
int ringBufferSize = 8;
for(int i = startPos, i != endPos, i = (i+1) % ringBufferSize) {
print buffer.getElementAt(i);
}
在 Python 中有没有办法轻松做到这一点?我只找到了
for i in list:
print buffer[i]
语法但没有为我的问题提供等效的解决方案。
我的下一个方法是在迭代存储在列表中的索引之前预先创建列表。但是有没有办法像在其他编程语言中那样通过直接在 for 循环中使用模运算来像在其他编程语言中一样单行执行此操作?
使用范围
for i in range(0,len(a)):
#code
i=i%x
For 循环可以采用任何可迭代对象。因此,您可以创建自己的来完成工作并将其放入 for 循环中。例如:
for i in [i % ring_buffer for i in range(start_pos, end_pos)]:
# Do stuff...
或者,直接创建一个可迭代对象:
for i in (i % ring_buffer for i in range(start_pos, end_pos)):
# Do stuff...
请参阅 the docs 了解有关何时可能需要为此目的直接创建迭代器的详细信息。
你有一些方法可以做到这一点:
正如您在 "other programing languages" 中所做的那样(即 C 派生语法),只是您基本上必须以 while 形式编写它们的 for
循环 - 然后您意识到 C 的 for 只是一个while
尽管如此:
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" - 它总是遍历一个可迭代对象或序列。所以你可以创建一个迭代器来产生你的值 -
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
请注意,虽然第二种形式是 "bigger",但它确实抽象了您的循环缓冲区逻辑,避免了硬代码值在您不需要查看它们的地方与它们的含义混淆 - 也就是说, 在 for
主体内部。
请注意 Python 中 for
的实际想法是遍历 缓冲区 内容本身,而不是指向其内容的索引.
因此,Python 标准库包含一个现成的循环缓冲区对象,它的索引始终规范化为 0 和 (len - 1) -
只需从 collections
模块导入 deque
。
如果你想要一个循环缓冲区,其开始和结束索引会改变,taht 将环绕并在 for
语句中自动工作,这也相对容易做到 - 如果你不需要完整的功能,只需子类化list
,添加 start
和 end
索引,并对其 __iter__
方法进行自定义实现:
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)]
现在您可以在代码中使用这个自定义容器了:
In [22]: mylist = Circular(range(8), 6 , 2)
In [23]: for i in mylist:
...: print(i)
...:
6
7
0
1
我相信您应该能够使用 while
而不是 for
循环。只要您只想每次将 i
递增 1,然后计算 mod.
,这应该可以工作
尝试:
i = startPos
while (i <= endPos and i == (i+1) % ringBufferSize) :
print buffer.getElementAt(x)
i = i+1
是否可以使用模运算创建 python for 循环?我在 Python 中有一个环形缓冲区,我想迭代 startPos
和 endPos
索引之间的元素,其中 startPos
的值可以大于 endPos
。在其他编程语言中,我会直观地使用模运算符来实现它:
int startPos = 6;
int endPos = 2;
int ringBufferSize = 8;
for(int i = startPos, i != endPos, i = (i+1) % ringBufferSize) {
print buffer.getElementAt(i);
}
在 Python 中有没有办法轻松做到这一点?我只找到了
for i in list:
print buffer[i]
语法但没有为我的问题提供等效的解决方案。
我的下一个方法是在迭代存储在列表中的索引之前预先创建列表。但是有没有办法像在其他编程语言中那样通过直接在 for 循环中使用模运算来像在其他编程语言中一样单行执行此操作?
使用范围
for i in range(0,len(a)):
#code
i=i%x
For 循环可以采用任何可迭代对象。因此,您可以创建自己的来完成工作并将其放入 for 循环中。例如:
for i in [i % ring_buffer for i in range(start_pos, end_pos)]:
# Do stuff...
或者,直接创建一个可迭代对象:
for i in (i % ring_buffer for i in range(start_pos, end_pos)):
# Do stuff...
请参阅 the docs 了解有关何时可能需要为此目的直接创建迭代器的详细信息。
你有一些方法可以做到这一点:
正如您在 "other programing languages" 中所做的那样(即 C 派生语法),只是您基本上必须以 while 形式编写它们的 for
循环 - 然后您意识到 C 的 for 只是一个while
尽管如此:
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" - 它总是遍历一个可迭代对象或序列。所以你可以创建一个迭代器来产生你的值 -
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
请注意,虽然第二种形式是 "bigger",但它确实抽象了您的循环缓冲区逻辑,避免了硬代码值在您不需要查看它们的地方与它们的含义混淆 - 也就是说, 在 for
主体内部。
请注意 Python 中 for
的实际想法是遍历 缓冲区 内容本身,而不是指向其内容的索引.
因此,Python 标准库包含一个现成的循环缓冲区对象,它的索引始终规范化为 0 和 (len - 1) -
只需从 collections
模块导入 deque
。
如果你想要一个循环缓冲区,其开始和结束索引会改变,taht 将环绕并在 for
语句中自动工作,这也相对容易做到 - 如果你不需要完整的功能,只需子类化list
,添加 start
和 end
索引,并对其 __iter__
方法进行自定义实现:
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)]
现在您可以在代码中使用这个自定义容器了:
In [22]: mylist = Circular(range(8), 6 , 2)
In [23]: for i in mylist:
...: print(i)
...:
6
7
0
1
我相信您应该能够使用 while
而不是 for
循环。只要您只想每次将 i
递增 1,然后计算 mod.
尝试:
i = startPos
while (i <= endPos and i == (i+1) % ringBufferSize) :
print buffer.getElementAt(x)
i = i+1