Я не совсем понимаю, когда мне следует использовать логические и побитовые операторы
and
против&
or
против|
Может ли кто-нибудь объяснить мне, когда я использую каждый из них и когда использование одного над другим повлияет на мои результаты?
Я не совсем понимаю, когда мне следует использовать логические и побитовые операторы
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.&
и |
являются регулярными операторами и могут быть перегружены - and
и or
подделываются на языке (хотя, по крайней мере, в Python, специальный метод принуждения к булевому может иметь побочные эффекты).and
и or
return (всегда? никогда не понимаю это и не нуждаюсь в нем) значение операнда вместо 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
is 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 logic.
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
>>>
Подсказка в названии:
Хотя возможно и даже иногда желательно (как правило, из соображений эффективности) выполнять логические операции с побитовыми операторами, обычно следует избегать их для таких целей, чтобы предотвратить незначительные ошибки и нежелательные побочные эффекты.
Если вам нужно манипулировать битами, то побитовые операторы специально созданы. Веселая книга: Hackers Delight содержит несколько классных и по-настоящему полезных примеров того, чего можно достичь с помощью хитрости.
Общее правило заключается в использовании соответствующего оператора для существующих операндов. Используйте логические (логические) операторы с булевыми операндами и побитовые операторы с (более широкими) интегральными операндами (примечание: False эквивалентно 0, а True - 1). Единственный "хитрый" сценарий - применение булевых операторов к не булевым операндам.
Давайте возьмем простой пример, как описано в [SO]: Python - Различия между 'и' и '&' [duplicate]: 5 & 7
против 5 and 7
.
Для побитового и (&) все довольно просто:
5 = 0b101 7 = 0b111 ----------------- 5 & 7 = 0b101 = 5
Для логического и, вот что [Python 3]: булевы операции состояния (акцент мой):
(Обратите внимание, что ни и ни, ни ограничение этих значений и типов не возвращаются в False и True, а скорее возвращают последний оцененный аргумент
Пример:
>>> 5 and 7 7 >>> 7 and 5 5
Конечно, то же самое относится и к | против или.
Boolean 'и' vs. Bitwise '&':
Псевдокод/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)) выполняются одновременно, тогда тело условного оператора может быть выполнено.
Побитовые операции
Побитовые операции могут использоваться для манипулирования данными и извлечения. Например, если вы хотите извлечь четыре младших значащих бита младшего разряда из целого числа, вы можете сделать это:
Экстракция:
poo & 0x000F
Маскировка:
poo | 0xFFF0