布尔运算符与按位运算符
-
27-09-2019 - |
题
我很困惑何时应该使用布尔运算符和按位运算符
and
与&
or
与|
有人可以告诉我何时使用其中一种以及何时使用其中一种会影响我的结果吗?
解决方案
以下是一些指导原则:
- 布尔运算符通常用于 布尔值 值,但通常使用按位运算符 整数 价值观。
- 布尔运算符是 短路 但按位运算符是 不是 短路。
短路行为在如下表达式中很有用:
if x is not None and x.foo == 42:
# ...
这不能正确地与按位一起工作 &
运算符,因为双方总是会被评估,给出 AttributeError: 'NoneType' object has no attribute 'foo'
. 。当你使用布尔值时 and
当第一个表达式为 False 时,不计算第二个表达式。相似地 or
如果第一个参数为 True,则不计算第二个参数。
其他提示
理论上, and
和 or
直接来自布尔逻辑(因此对两个布尔值进行运算以产生一个布尔值),而 &
和 |
将布尔值和/或应用于整数的各个位。关于后者究竟如何工作,有很多问题。
以下是可能影响您的结果的实际差异:
and
和or
短路,即True or sys.exit(1)
不会退出,因为对于某个值(True or ...
,False and ...
) 第一个操作数,第二个操作数不会改变结果 = 不需要计算。但|
和&
不要短路-True | sys.exit(1)
让你脱离 REPL。- (仅适用于某些?具有运算符重载的语言,包括 Python:)
&
和|
是常规运算符并且可以重载 -and
和or
被锻造到语言中(尽管至少在Python中,强制转换为布尔值的特殊方法可能会产生副作用)。 - (仅适用于几种语言[参见 KennyTM 的评论]:)
and
和or
返回(总是?从来没有真正理解这一点,我也不需要它)操作数的值而不是True
或者False
. 。这不会改变条件中布尔表达式的含义 -1 or True
是1
, , 但1
也是如此。但它曾经被用来模拟条件运算符(cond ? true_val : false_val
在 C 语法中,true_val if cond else false_val
几年以来一直在使用Python)。为了&
和|
, ,结果类型取决于操作数如何重载各自的特殊方法(True & False
是False
,99 & 7
是3
, ,对于集合来说它是并集/交集...)。
但即使例如 a_boolean & another_boolean
会同样工作,正确的解决方案是使用 and
- 仅仅是因为 and
和 or
与布尔表达式和条件相关联,而 &
和 |
代表有点摆弄。
还有一个区别,刚才让我困惑了一段时间:因为 &
(和其他按位运算符)的优先级高于 and
(和其他布尔运算符)以下表达式计算出不同的值:
0 < 1 & 0 < 2
相对
0 < 1 and 0 < 2
也就是说,第一个产生 False
因为它相当于 0 < (1 & 0) < 2
, , 因此 0 < 0 < 2
, , 因此 0 < 0 and 0 < 2
.
如果您尝试在中进行逐元素布尔运算 numpy
, ,答案有些不同。您可以使用 &
和 |
对于逐元素布尔运算,但是 and
和 or
将返回值错误。
为了安全起见,您可以使用 numpy 逻辑函数.
np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False, True], dtype=bool)
np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False, True], dtype=bool)
布尔运算是逻辑运算。
位运算是对二进制位的运算。
按位运算:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
操作:
And & 1 if both bits are 1, 0 otherwise
Or | 1 if either bit is 1
Xor ^ 1 if the bits are different, 0 if they're the same
Not ~ Flip each bit
位运算的一些用途:
1) 设置和清除位
布尔运算:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
提示就在名字中:
- 布尔运算符用于执行 逻辑运算 (真实性测试常见于编程和形式逻辑)
- 位运算符用于 “小玩意儿” (字节和数字数据类型中位的低级操作)
虽然可以并且有时确实需要(通常出于效率原因)使用按位运算符执行逻辑运算,但您通常应该避免出于此类目的使用它们,以防止微妙的错误和不需要的副作用。
如果您需要操作位,那么按位运算符是专门构建的。有趣的书: 黑客之乐 包含一些很酷且真正有用的示例,说明通过位操作可以实现什么。
一般规则是对现有操作数使用适当的运算符。将布尔(逻辑)运算符与布尔操作数一起使用,将按位运算符与(更广泛的)整数操作数一起使用(注意: 错误的 相当于 0, , 和 真的 到 1)。唯一“棘手”的场景是将布尔运算符应用于非布尔操作数。
让我们举一个简单的例子,如中所述 [所以]:Python - “and”和“&”之间的区别[重复]: 5 & 7
与 5 and 7
.
为了 按位 和 (&),事情非常简单:
5 = 0b101 7 = 0b111 ----------------- 5 & 7 = 0b101 = 5
为了 逻辑的 和, ,这就是 [Python 3]:布尔运算 状态 (强调 是我的):
例子:
>>> 5 and 7 7 >>> 7 and 5 5
当然,同样适用于 | 与 或者.
布尔“与”对比按位“&”:
伪代码/Python 帮助我理解了它们之间的区别:
def boolAnd(A, B):
# boolean 'and' returns either A or B
if A == False:
return A
else:
return B
def bitwiseAnd(A , B):
# binary representation (e.g. 9 is '1001', 1 is '0001', etc.)
binA = binary(A)
binB = binary(B)
# perform boolean 'and' on each pair of binaries in (A, B)
# then return the result:
# equivalent to: return ''.join([x*y for (x,y) in zip(binA, binB)])
# assuming binA and binB are the same length
result = []
for i in range(len(binA)):
compar = boolAnd(binA[i], binB[i])
result.append(compar)
# we want to return a string of 1s and 0s, not a list
return ''.join(result)
逻辑运算
通常用于条件语句。例如:
if a==2 and b >10 then
/*Do something...*/
endif
这意味着如果两个条件((a==2)(b>10))同时为真,则可以执行条件语句体。
按位运算
位运算可用于数据操作和提取。例如,如果你想提取一个整数的四个LSB(最低有效位),你可以这样做:
萃取:
poo & 0x000F
掩蔽:
poo | 0xFFF0