布尔运算符与按位运算符
我对什么时候使用布尔运算符和位运算符有点困惑。
and
和&
or
和|
能不能给我讲讲我该什么时候用它们?用一个比另一个会对我的结果有什么影响吗?
9 个回答
28
理论上来说,and
和 or
是来自布尔逻辑的运算符(它们操作两个布尔值并返回一个布尔值),而 &
和 |
则是对整数的每一位进行布尔运算。关于后者的具体工作原理,有很多问题。
以下是一些可能影响你结果的实际区别:
and
和or
有短路特性,比如True or sys.exit(1)
不会退出,因为在某些情况下,第一个操作数的值(比如True or ...
或False and ...
)已经决定了结果,第二个操作数就不需要计算了。但|
和&
没有短路特性——True | sys.exit(1)
会直接让你退出。&
和|
是普通的运算符,可以被重载,而and
和or
是语言本身的一部分(虽然强制转换为布尔值的特殊方法可能会有副作用)。- 这也适用于一些其他支持运算符重载的语言。
and
和or
返回的是操作数的值,而不是True
或False
。这并不改变布尔表达式在条件中的含义——例如,1 or True
的结果是1
,但1
也是 true。不过,这曾经被用来模拟条件运算符(在 C 语言中是cond ? true_val : false_val
,在 Python 中是true_val if cond else false_val
)。对于&
和|
,结果的类型取决于操作数如何重载各自的特殊方法(比如True & False
是False
,99 & 7
是3
,对于集合则是并集/交集等)。- 这也适用于一些其他语言,比如 Ruby、Perl 和 Javascript。
但是即使例如 a_boolean & another_boolean
的结果是一样的,正确的做法还是使用 and
——因为 and
和 or
是与布尔表达式和条件相关的,而 &
和 |
则是用于位运算的。
31
这里有一个我刚才困惑了一会儿的区别:因为 &
(还有其他位运算符)优先级比 and
(还有其他布尔运算符)高,所以下面这两个表达式的结果是不同的:
0 < 1 & 0 < 2
和
0 < 1 and 0 < 2
具体来说,第一个表达式的结果是 False
,因为它等同于 0 < (1 & 0) < 2
,所以变成了 0 < 0 < 2
,进一步变成 0 < 0 and 0 < 2
。
108
这里有几个简单的指导原则:
- 布尔运算符通常用于布尔值,而位运算符通常用于整数值。
- 布尔运算符是短路的,而位运算符则不是短路的。
短路的特性在这样的表达式中非常有用:
if x is not None and x.foo == 42:
# ...
如果用位运算符&
,这个表达式就会出错,因为两边的值都会被计算,可能会出现AttributeError: 'NoneType' object has no attribute 'foo'
的错误。而如果用布尔运算符and
,当第一个表达式为假时,第二个表达式就不会被计算。同样地,如果第一个表达式为真,or
就不会计算第二个表达式。