Python 使用iter()和sentinel替换while循环
通常情况下,需要无限期地循环,直到达到某个条件。例如,如果我想继续收集随机整数,直到我找到一个数==n,然后断开。我会这样做:Python 使用iter()和sentinel替换while循环,python,generator,Python,Generator,通常情况下,需要无限期地循环,直到达到某个条件。例如,如果我想继续收集随机整数,直到我找到一个数==n,然后断开。我会这样做: import random rlist = [] n = ... low, high = ..., ... while True: num = random.randint(low, high) if num == n: break rlist.append(num) 这是可行的,但相当笨重。还有一种更具python风格的替代
import random
rlist = []
n = ...
low, high = ..., ...
while True:
num = random.randint(low, high)
if num == n:
break
rlist.append(num)
这是可行的,但相当笨重。还有一种更具python风格的替代方法,使用:
iter(o[哨兵])
返回一个迭代器对象。第一个论点是
根据第二种情况的不同,解释非常不同
论点[…]如果第二个参数,
sentinel,则o必须是可调用的对象。迭代器
在本例中创建的将调用o,每个调用都没有参数
它的next()
方法;如果返回的值等于sentinel,
将引发StopIteration,否则将返回值
上面的循环可以替换为
import random
from functools import partial
f = partial(random.randint, low, high)
rlist = list(iter(f, 10))
为了将这一原则扩展到已经创建的列表,需要做一些细微的更改。我需要定义如下的分部函数:
f = partial(next, iter(x)) # where x is some list I want to keep taking items from until I hit a sentinel
其余部分保持不变,但与while循环相比,这种方法的主要警告是我不能应用一般的布尔条件
例如,我无法应用“在遇到第一个大于1000的偶数之前生成数字”
底线是:除了while循环和
iter
之外,还有其他支持回调sentinel的替代方案吗?如果您需要通用布尔条件,那么iter(object,sentinel)
对您的需求表达不足<相反,code>itertools.takewhile()似乎或多或少是您想要的:它接受一个迭代器,并在给定谓词停止为true时将其截断
rlist = list(itertools.takewhile(lambda x: x >= 20, inputlist))
顺便说一句,
partial
不是很像Pythonic,itertools
也不是。GvR不喜欢高阶函数式编程(注意reduce
在3.0中从内置降级为模块成员)。像“优雅”和“可读”这样的属性在旁观者的眼里,但是如果你在寻找纯粹意义上的Pythonic,你需要while循环。如果你想要一般的布尔条件,那么iter(object,sentinel)
对于你的需求来说是不够表达的<相反,code>itertools.takewhile()似乎或多或少是您想要的:它接受一个迭代器,并在给定谓词停止为true时将其截断
rlist = list(itertools.takewhile(lambda x: x >= 20, inputlist))
顺便说一句,
partial
不是很像Pythonic,itertools
也不是。GvR不喜欢高阶函数式编程(注意reduce
在3.0中从内置降级为模块成员)。像“优雅”和“可读”这样的属性在旁观者的眼里,但如果你想从最纯粹的意义上寻找Pythonic,你需要while循环。为什么while
循环“笨重”?谁在没有解释的情况下投了反对票?有什么课吗?有点笨重而且过时。不过我并不反对。只是想探索其他的选择。另外,我也希望落选的选民能发表评论。希望有机会修正任何错误。为什么while
循环“笨重”?谁在没有解释的情况下投了反对票?有什么课吗?有点笨重而且过时。不过我并不反对。只是想探索其他的选择。另外,我也希望落选的选民能发表评论。希望有机会修正任何错误。太棒了。这正是我想要的。一种iter
,能够接受回调作为哨兵。将在我可以的时候接受。@Sneftelpartial
被添加为GvR试图摆脱lambda
的一部分itertools
实现流处理,流处理与函数式编程有着密切的联系,但不是一回事。这两种语言都不是Pythonic,只是不被认为是核心语言所必需的。(不过,itertools
的一部分正在向核心语言转移。例如,内置的map
和filter
取代了itertools.imap
和itertools.ifilter
)非常出色。这正是我想要的。一种iter
,能够接受回调作为哨兵。将在我可以的时候接受。@Sneftelpartial
被添加为GvR试图摆脱lambda
的一部分itertools
实现流处理,流处理与函数式编程有着密切的联系,但不是一回事。这两种语言都不是python语言,只是不被认为是核心语言所必需的。(不过,itertools
的一部分正在转向核心语言。例如,内置的map
和filter
取代了itertools.imap
和itertools.ifilter
)