在 C 语言中,我会这样做:
int i;
for (i = 0;; i++)
if (thereIsAReasonToBreak(i))
break;
如何在 Python 中实现类似的功能?
itertools.count
:
import itertools
for i in itertools.count(start=1):
if there_is_a_reason_to_break(i):
break
在 Python 2 中,
range()
和 xrange()
仅限于 sys.maxsize
。在 Python 3 中 range()
可以更高,但不会达到无穷大:
import sys
for i in range(sys.maxsize**10): # you could go even higher if you really want
if there_is_a_reason_to_break(i):
break
所以最好使用
count()
。
def to_infinity():
index = 0
while True:
yield index
index += 1
for i in to_infinity():
if i > 10:
break
最简单最好的:
i = 0
while not there_is_reason_to_break(i):
# some code here
i += 1
选择与 Python 中的 C 代码最接近的类比可能很诱人:
from itertools import count
for i in count():
if thereIsAReasonToBreak(i):
break
但要注意,修改
i
不会像在C中那样影响循环的流程。因此,使用while
循环实际上是将C代码移植到Python的更合适的选择。
重申thg435的评论:
from itertools import takewhile, count
def thereIsAReasonToContinue(i):
return not thereIsAReasonToBreak(i)
for i in takewhile(thereIsAReasonToContinue, count()):
pass # or something else
或者更简洁地说:
from itertools import takewhile, count
for i in takewhile(lambda x : not thereIsAReasonToBreak(x), count()):
pass # or something else
takewhile
模仿“行为良好”的 C for 循环:你有一个延续条件,但你有一个生成器而不是任意表达式。您可以在 C for 循环中执行一些“行为不当”的操作,例如修改循环体中的 i
。如果生成器是某个局部变量 takewhile
的闭包,那么您也可以使用 i
来模仿它们。在某种程度上,定义该闭包使得您正在做一些可能与您的控制结构混淆的事情变得特别明显。
def infinity():
i=0
while True:
i+=1
yield i
for i in infinity():
if there_is_a_reason_to_break(i):
break
如果你在 C 中这样做,那么你的判断就和在 Python 中一样模糊:-)
对于在每次迭代开始时通过简单条件检查退出的循环,更常见(在我看来更清晰)是在循环构造本身中执行此操作。换句话说,类似(如果循环结束后需要
i
):
int i = 0;
while (! thereIsAReasonToBreak(i)) {
// do something
i++;
}
或(如果
i
的范围可以限定为 just 循环):
for (int i = 0; ! thereIsAReasonToBreak(i); ++i) {
// do something
}
这将转化为 Python 的等价物:
i = 0
while not there_is_a_reason_to_break(i):
# do something
i += 1
只有当您需要在循环的“中间”某个地方退出时(或者如果您的条件足够复杂以至于会使循环语句的可读性大大降低),您才需要担心中断。 当您的潜在退出是循环的
start处的一个简单退出时(正如此处所示),通常最好将退出编码到循环本身中。
for
而不是
while
以及更改 variable
的值来影响循环的功能,这里有一个面向对象的解决方案:class Count:
def __init__(self, start):
self.count = start - 1
def increment(self):
self.count += 1
def set(self, number):
self.count = number - 1
# Since __next__ method directly increments, to balance that `-1` is used in Count class.
class InfiniteIter:
def __init__(self, start):
self.count = Count(start)
def __iter__(self):
return self
def __next__(self):
self.count.increment()
return self.count
for i in InfiniteIter(1):
print(i.count)
if i.count == 5:
i.set(10)
input() # for testing purpose
说明:
for
循环在完成每次迭代后调用
__next__
方法,返回一个Count
对象。
Count
对象有一个方法
set
用于设置 count
属性的值。
__next__
方法直接递增,以平衡
-1
在 Count 类中使用。
Count
对象
count
属性可用于访问值。 (也可用于设置值,但由于第3点,该数字已为-1)