首页 > 深入Python > 自省的威力 > and-or 的特殊性质 | << >> | ||||
diveintopython.org Python for experienced programmers |
在Python中,and 和 or 执行布尔逻辑,如你所期待的一样,但是它们并不返回布尔值;它们返回正在比较的真实值之一。
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c'
当使用 and,在一个布尔上下文中值的计算是从左向右进行的。0, '', [], (), {}, 和 None 在布尔上下文中是假;其它的所有东西都是真。[3] 如果在一个布尔上下文中所有的值都为真,and 返回最后一个值。在本例中,and 计算 'a',结果是真,接着是 'b',结果是真,则返回 'b'。 | |
如果在一个布尔上下文中有一个值为假,and 返回第一个假值。在本例中,'' 是第一个假值。 | |
所有的值的真,所以 and 返回最后的值 'c'。 |
>>> 'a' or 'b' 'a' >>> '' or 'b' 'b' >>> '' or [] or {} {} >>> def sidefx(): ... print "in sidefx()" ... return 1 >>> 'a' or sidefx() 'a'
如果你是一名C语言高手,当然对 bool ? a : b 表达式熟悉,这个表达式当 bool 为真时计算为 a,其它值则为 b。由于Python中 and 和 or 的工作方式,你可以完成相同的事情。
>>> a = "first" >>> b = "second" >>> 1 and a or b 'first' >>> 0 and a or b 'second'
这个语法看起来与C语言中的 bool ? a : b 相似。整个表达式从左向右计算,所以 and 首先执行。1 and 'first' 计算为 'first',然后 'first' or 'second' 计算为 'first'。 |
|
0 and 'first' 计算为 0,然后 0 or 'second' 计算为 'second'。 |
然而,因为这个Python表达式是简单的布尔逻辑,而不是一个特殊的语言结构,所以在这个Python的 and-or 技巧与C中的 bool ? a : b 语法之间,有一个非常,非常,非常重要的不同。如果 a 的值为假,表达式将不会按你期望的那样执行。(你能知道我被这个问题折腾过吗?不只一次?)
>>> a = "" >>> b = "second" >>> 1 and a or b 'second'
这个 and-or 技巧,bool and a or b,当 a 为假时,不会象C表达式 bool ? a : b 一样工作。 |
那么在 and-or 技巧之后的真正的技巧是确信 a 的值永远不为假。实现这一点的通常的方法之一是将 a 转化为 [a] 并且将 b 转化为 [b],接着使用返回的列表的第一个元素,应为 a 或 b。
>>> a = "" >>> b = "second" >>> (1 and [a] or [b])[0] ''
到现在为止,这个技巧可能看上去问题超过了它的价值。毕竟你可以用一个 if 语句完成相同的事情,那么为什么要经受这些麻烦呢?哦,在很多情况下,要在两个常量之间进行选择,所以可以使用更简单的语法而不必担心,因为你知道 a 值将总是真。并且尽管你不得不使用更复杂的安全形式,也有一些好的理由来使用这个技巧;在Python中有很多时候, if 语句不允许使用, 象 lambda 函数。
进一步阅读
脚注
[3] 好,几乎都在这儿了。缺省地,类的实例在一个布尔上下文中是真,但是你可以在你的类中定义特别的方法使得一个实例的计算为假。你将在第三章中学习所有关于类和特殊方法的内容。
Filtering lists |
1 2 3 4 5 6 7 8 9 |
Using lambda functions |
« 过滤列表 | 使用 lambda 函数 » |