Python 布尔表达式与或
在Python中,如果你写了类似这样的代码:
foo==bar and spam or eggs
当布尔表达式为真时,Python会返回“spam”,如果为假则返回“eggs”。有人能解释一下这是为什么吗?为什么这个表达式没有像一个长的布尔表达式那样被评估?
补充说明:具体来说,我想弄清楚为什么“spam”或“eggs”会作为这个表达式的结果返回。
4 个回答
原因是,Python在判断布尔表达式时,会使用变量的实际值,而不是仅仅局限于True
和False
这两个值。以下这些值被认为是假的:
None
(表示没有值)False
(布尔假值)- 任何数字类型的0
- 空的序列或集合(比如
''
、()
、[]
、{}
) - 用户自定义类型,如果它们的
__nonzero__()
或__len__()
方法返回0或False
,也会被认为是假的
想了解更多信息,可以查看Python文档中的真值测试部分。特别是:
那些返回布尔结果的操作和内置函数,通常会返回
0
或False
表示假,返回1
或True
表示真,除非另有说明。(重要的例外是:布尔操作or
和and
总是返回它们的一个操作数。)
下面是Python中的布尔运算符是怎么工作的。
根据官方文档(最后一段解释了为什么这些运算符的工作方式是个好主意):
在布尔运算的上下文中,以及在控制流语句中使用表达式时,以下值会被视为假:
False
、None
、所有类型的数字零,以及空字符串和空容器(包括字符串、元组、列表、字典、集合和不可变集合)。其他所有值都被视为真。(可以查看__nonzero__()
这个特殊方法,了解如何改变这一点。)运算符
not
会返回True
,如果它的参数是假的;如果参数是真的,则返回False
。表达式
x and y
会先计算x
;如果x
是假的,就返回x
的值;如果x
是真的,就计算y
并返回y
的值。表达式
x or y
同样先计算x
;如果x
是真的,就返回x
的值;如果x
是假的,就计算y
并返回y
的值。(注意,
and
和or
并不限制返回的值和类型为False
和True
,而是返回最后计算的参数。这有时很有用,比如,如果s
是一个字符串,应该在它为空时用默认值替换,那么表达式s or 'foo'
就能得到想要的值。因为not
无论如何都要返回一个值,所以它不在乎返回的值类型和参数相同,因此例如not 'foo'
会返回False
,而不是''
。)
运算符 and
和 or
是短路运算,这意味着如果通过只看第一个操作数就能判断出结果,那么第二个操作数就不会被计算。例如,如果你有表达式 a or b
,而 a
的值为真,那么 b
的值就不重要了,结果就是真,所以 b
不会被计算。它们的工作原理如下:
a and b
: 如果a
的值为假,那么b
不会被计算,直接返回a
;如果a
为真,则返回b
。a or b
: 如果a
的值为真,那么b
不会被计算,直接返回a
;如果a
为假,则返回b
。
假值和真值是指在布尔上下文中被判断为假或真的值。
不过,这种 and/or
的用法在以前没有更好选择的时候很有用,但现在有更好的方法了:
spam if foo==bar else eggs
使用 and/or
的问题(除了对初学者来说可能会让人困惑)是,如果条件为真但 spam
计算出的值是个假值(比如空字符串),那么结果就会错误。因此,最好避免使用这种写法。