and
和or
返回他们评估的最后一个元素,但为什么Python的内置函数any
没有?
我的意思是这样实现自己很容易,但我仍然想知道为什么。
def any(l):
for x in l:
if x:
return x
return x
编辑:
要添加到下面的答案,这里是你们强大的皇帝在同一个邮件列表中的实际引用:
是否总是返回True和False或第一次faling / pass 元件?在博客之前我也玩过这个,并意识到了 结束案例(如果序列为空或者所有元素都未通过测试) 永远不能令人满意的工作:选择没有感觉很奇怪,如果 参数是一个可迭代的bools,如果选择False会觉得很奇怪 参数是一个可迭代的非bool对象。
Guido van Rossum(主页:http://www.python.org/~guido/)
答案 0 :(得分:44)
这个问题出现在2005年Python开发人员的邮件列表中,当时Guido Van Rossum建议在Python 2.5中添加any
和all
。
Bill Janssen requested将其实施为
def any(S):
for x in S:
if x:
return x
return S[-1]
def all(S):
for x in S:
if not x:
return x
return S[-1]
执行any
和all
,responded的Raymond Hettinger专门解决了为什么any
和all
不采取行动{{1} }和and
:
随着时间的推移,我得到了关于这些和其他itertools食谱的反馈。 没有人反对这些食谱中的真/假返回值 在Guido的版本中。
Guido的版本符合任何/所有人的正常期望 谓语。此外,它避免了人们的那种错误/混乱 目前使用Python"和"的独特实现经验和 "或"
返回最后一个元素并不邪恶;它只是奇怪,出乎意料,而且 非显而易见的。抵制这个变得棘手的冲动。
邮件列表在很大程度上得到了同意,现在就像你今天看到的那样实现了。
答案 1 :(得分:20)
and
和or
可以通过始终返回其中一个操作数的方式明智地定义。但是,any
和all
无法合理地定义从输入序列返回值:具体而言,当列表为空时,它们不能这样做。在这种情况下,any
和all
目前都有明确定义的结果:any
返回False,all
返回True。您将被迫有时返回一个布尔值,有时从序列中返回一个项目,这会产生令人不快和令人惊讶的界面。简单而一致的好多了。
答案 2 :(得分:5)
我问了同样的问题on python-ideas,并被告知原因是any()
和all()
需要在序列为空时返回值,并且这些值必须为{{ 1}}和False
。这对我来说似乎是一个微弱的争论。
这些函数现在不能改变,但我认为它们会更有用,并且如果它们返回第一个真正的或者是假的,它们会更好地模拟它们概括的True
和and
运算符。 - 他们遇到的价值。
答案 3 :(得分:3)
由于历史原因,and
和or
的行为存在。
在Python有三元操作/条件表达式之前,如果要在条件上使用值,则使用and
和or
。可以使用条件表达式语法重写任何此类表达式:
true_val if condition else false_val
基本上,它们有两个功能超载,出于兼容性原因,它们没有被更改。
这是不超载其他操作的原因。 any
似乎应该告诉你条件是否适用于任何项,这是一个布尔值,因此它应该返回bool
。
答案 4 :(得分:0)
Any
返回一个布尔值,因为它有效地将其参数视为bool列表,然后再考虑它们是否为真。 返回它评估的元素,但这恰好是一个bool。
您希望何时使用自己的any
版本?如果它在bool列表中,那么你已经有了正确的答案。否则你只是在防范None
,可能表达为:
filter(lambda x: x != None, l)[0]
或:
[x for x in l if x != None][0]
更明确的意图声明。
答案 5 :(得分:0)
any
的值可能是False或输入中的某个值并不是很明显。此外,大多数用途看起来像
tmp = any(iterable)
if tmp:
tmp.doSomething()
else:
raise ValueError('Did not find anything')
那是Look Before You Leap因此是unpythonic。比较:
next(i for i in iterable if i).doSomething()
# raises StopIteration if no value is true
and
和or
的行为在历史上非常有用,可作为当时不可用的条件表达式的插入。
答案 6 :(得分:0)
从Python 3.8
开始,并引入assignment expressions (PEP 572)(:=
运算符),我们可以替代地显式捕获any
表达式的 witness 或all
表达式的反例:
引用PEP description中的几个示例:
if any(len(long_line := line) >= 100 for line in lines):
print("Extremely long line:", long_line)
if all((nonblank := line).strip() == '' for line in lines):
print("All lines are blank")
else:
print("First non-blank line:", nonblank)