我刚刚在我的代码中遇到了一个奇怪的错误,因为我在条件而不是and
关键字中使用了逗号。请参阅下面的代码,了解淡化示例:
def foo():
s = set([1, 2, 3])
a = 4
b = 5
if (a, b in s): # Should have been: if (a and b in s):
print "Foo"
foo() # prints "Foo"
为什么条件评估为True
?即使a
为None
,也会打印“Foo”。
答案 0 :(得分:7)
表达式(a, b in s)
是一个有效的Python元组。只要它至少有一个元素,它将评估真理,无论其内容如何。 (这个有两个)。
答案 1 :(得分:3)
因为(a, b in s)
计算长度为2元组(4, False)
,而在python中,如果元组长度非零,则认为元组为True
。
答案 2 :(得分:2)
代码打印的原因' Foo'无论a和n的值是多少,在s中的是:
(a, b in s)
实际上是一个元组。 if语句检查元组是否存在,并且它确实打印了Foo。 当
s=set([1,2,3])
a=None
b=5
检查的条件是
if(None, False):
这总是正确的,因为
(None, False) #is a non empty tuple.
答案 3 :(得分:0)
正如其他人所说,表达式a, b in s
创建一个元组,非空元组是真实的,即它在布尔上下文中求值为True
。请注意,逗号创建元组而不是括号,尽管在某些上下文中需要括号以避免歧义,例如将元组文字作为单个函数参数传递时。
顺便说一句,在Python中if
语句的条件表达式周围不需要括号。他们不会受到伤害,但通常的风格习惯是将它们省略为不必要的混乱。
请注意,如果if a and b in s:
和a
都是集合b
的元素,则s
会不进行测试。要执行该测试,您应该使用set.issuperset
方法:
if s.issuperset((a, b)):
请注意,我们需要额外的括号,因为我们将元组a, b
作为单个参数传递。
也可以使用.issuperset
:
if s >= set((a, b)):
但是当使用该形式时,两个操作数必须是集合(或frozensets),而完整方法将接受任何可迭代的其他 arg。
但是回到你的代码......表达式
a and b in s
相当于
a and (b in s)
如果a
为false-ish(即False
,0或空集合),则表达式的计算结果为a
和and
表达式的第二部分被忽略了。否则(当a
是真实的时候)and
表达式的第二部分被评估并且成为结果。
换句话说,如果a == 0
然后a and b in s
导致0,但如果a
是任何其他数字,那么a and b in s
将导致True
b
{1}}位于s
,如果False
不在b
,则会s
。有关详细信息,请参阅我对Assigning string with boolean expression的回答。