布尔运算符与按位运算符

106 投票
9 回答
67996 浏览
提问于 2025-04-16 04:53

我对什么时候使用布尔运算符和位运算符有点困惑。

  • and&
  • or|

能不能给我讲讲我该什么时候用它们?用一个比另一个会对我的结果有什么影响吗?

9 个回答

28

理论上来说,andor 是来自布尔逻辑的运算符(它们操作两个布尔值并返回一个布尔值),而 &| 则是对整数的每一位进行布尔运算。关于后者的具体工作原理,有很多问题。

以下是一些可能影响你结果的实际区别:

  1. andor 有短路特性,比如 True or sys.exit(1) 不会退出,因为在某些情况下,第一个操作数的值(比如 True or ...False and ...)已经决定了结果,第二个操作数就不需要计算了。但 |& 没有短路特性——True | sys.exit(1) 会直接让你退出。
  2. &| 是普通的运算符,可以被重载,而 andor 是语言本身的一部分(虽然强制转换为布尔值的特殊方法可能会有副作用)。
    • 这也适用于一些其他支持运算符重载的语言。
  3. andor 返回的是操作数的值,而不是 TrueFalse。这并不改变布尔表达式在条件中的含义——例如,1 or True 的结果是 1,但 1 也是 true。不过,这曾经被用来模拟条件运算符(在 C 语言中是 cond ? true_val : false_val,在 Python 中是 true_val if cond else false_val)。对于 &|,结果的类型取决于操作数如何重载各自的特殊方法(比如 True & FalseFalse99 & 73,对于集合则是并集/交集等)。
    • 这也适用于一些其他语言,比如 Ruby、Perl 和 Javascript。

但是即使例如 a_boolean & another_boolean 的结果是一样的,正确的做法还是使用 and——因为 andor 是与布尔表达式和条件相关的,而 &| 则是用于位运算的。

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就不会计算第二个表达式。

撰写回答