这个有条件的处理方式如何?

时间:2017-01-05 03:27:53

标签: python

我刚刚在我的代码中遇到了一个奇怪的错误,因为我在条件而不是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?即使aNone,也会打印“Foo”。

4 个答案:

答案 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或空集合),则表达式的计算结果为aand表达式的第二部分被忽略了。否则(当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的回答。