通常情况下,需要无限循环直到达到某种条件。 例如,如果我想继续收集随机整数,直到找到一个== 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。)