Python 使用iter()和sentinel替换while循环

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风格的替代

通常情况下,需要无限期地循环,直到达到某个条件。例如,如果我想继续收集随机整数,直到我找到一个数==n,然后断开。我会这样做:

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
,能够接受回调作为哨兵。将在我可以的时候接受。@Sneftel
partial
被添加为GvR试图摆脱
lambda
的一部分
itertools
实现流处理,流处理与函数式编程有着密切的联系,但不是一回事。这两种语言都不是Pythonic,只是不被认为是核心语言所必需的。(不过,
itertools
的一部分正在向核心语言转移。例如,内置的
map
filter
取代了
itertools.imap
itertools.ifilter
)非常出色。这正是我想要的。一种
iter
,能够接受回调作为哨兵。将在我可以的时候接受。@Sneftel
partial
被添加为GvR试图摆脱
lambda
的一部分
itertools
实现流处理,流处理与函数式编程有着密切的联系,但不是一回事。这两种语言都不是python语言,只是不被认为是核心语言所必需的。(不过,
itertools
的一部分正在转向核心语言。例如,内置的
map
filter
取代了
itertools.imap
itertools.ifilter