通常情况下,需要无限循环直到达到某种条件。 例如,如果我想继续收集随机整数,直到找到一个== n的数字,然后我将其破坏。 我会这样做:
import random
rlist = []
n = ...
low, high = ..., ...
while True:
num = random.randint(low, high)
if num == n:
break
rlist.append(num)
这行得通,但是很笨拙。 使用iter还有更多的pythonic替代方法:
iter(o[, sentinel])
Return an iterator object. The first argument is
interpreted very differently depending on the presence of the second
argument. [...] If the second argument,
sentinel, is given, then o must be a callable object. The iterator
created in this case will call o with no arguments for each call to
its next() method; if the value returned is equal to sentinel,
StopIteration will be raised, otherwise the value will be returned.
上面的循环可以替换为
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是否有另一种支持回调哨兵的方法?
为什么while循环"笨拙"?
谁在不加解释地投票? 上课吗
它有点笨重和老式。 我没有反对它。 只是想探索其他选择。 此外,将不满意落选者的评论。 希望有机会纠正任何错误。
如果需要通用布尔条件,则iter(object, sentinel)不能充分满足您的需求。 相反,itertools.takewhile()似乎或多或少是您想要的:它需要一个迭代器,并在给定谓词停止为真时将其切断。
rlist = list(itertools.takewhile(lambda x: x >= 20, inputlist))
顺便说一句,partial并不是Python语言,itertools也不是。 GvR被记录为不喜欢高阶函数式编程(请注意,将reduce从内置降级为3.0中的模块成员)。 旁观者认为"典雅"和"可读"之类的属性,但是如果您从最纯粹的意义上寻找Pythonic,则需要while循环。
辉煌。 这正是我想要的。 一个iter能够接受回调作为标记。 我会的时候接受。
@Sneftel partial被添加为GvR尝试摆脱lambda的一部分。 itertools实现流处理,该流处理与功能编程有密切关系,但不是同一件事。 两者都不都是非Python语言的,只是不被认为对核心语言至关重要。
(不过,itertools的某些部分正在转移到核心语言。例如,内置的map和filter替换了itertools.imap和itertools.ifilter。)