通常情况下,人们需要无限循环直到达到某个条件。例如,如果我想继续收集随机整数,直到我找到一个数字== 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])
返回一个迭代器对象。第一个论点是 根据第二个的存在,解释非常不同 论点。 [...]如果是第二个论点, 给定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
支持回调哨兵?
答案 0 :(得分:5)
如果您需要通用布尔条件,那么iter(object, sentinel)
表达不足以满足您的需求。相反,itertools.takewhile()
似乎或多或少是你想要的:它需要一个迭代器,并在给定的谓词停止为真时将其切断。
rlist = list(itertools.takewhile(lambda x: x >= 20, inputlist))
顺便说一下,partial
不是非常Pythonic,itertools
也不是。reduce
。 GvR记录为不喜欢高阶函数式编程(注意ParameterExpression<String>[] searchStrings = new ParameterExpression[10];
从内置降级到3.0中的模块成员)。像“优雅”和“可读”这样的属性在旁观者的眼中,但如果你在最纯粹的意义上寻找 Pythonic ,你需要while循环。