Мене бентежить, коли слід використовувати булеві та побітові оператори
and
проти&
or
проти|
Чи міг хтось просвітити мене щодо того, коли я використовую кожен і коли використання одного над іншим вплине на мої результати?
Мене бентежить, коли слід використовувати булеві та побітові оператори
and
проти &
or
проти |
Чи міг хтось просвітити мене щодо того, коли я використовую кожен і коли використання одного над іншим вплине на мої результати?
Відповіді:
Ось кілька рекомендацій:
Поведінка короткого замикання корисна у таких виразах:
if x is not None and x.foo == 42:
# ...
Це не буде коректно працювати з побітовим &
оператором, оскільки обидві сторони завжди оцінюватимуться, даючи AttributeError: 'NoneType' object has no attribute 'foo'
. Коли ви використовуєте логічний and
оператор, другий вираз не обчислюється, коли перший - False. Подібним or
чином не оцінює другий аргумент, якщо перший є True.
&
, |
, ^
встановлені операції теж.
True or "True"
це нормально (він поверне перше неправдиве значення), але True | "True"
видасть виняток.
0 == False
і 1 == True
обидва вони є true.
Теоретично, and
і or
виходити прямо з логічної логіки (і, отже, оперувати двома логічними значеннями для створення логічного значення), &
і |
застосовувати логічне значення та / або до окремих бітів цілих чисел. Тут є багато питань щодо того, як саме працюють останні.
Ось практичні відмінності, які потенційно можуть вплинути на ваші результати:
and
і or
коротке замикання, наприклад True or sys.exit(1)
, не вийде, оскільки для певного значення першого операнда ( True or ...
, False and ...
) другий не змінить результат, тому не потрібно обчислювати. Але |
і &
не замикайте коротке замикання - True | sys.exit(1)
викидає вас за межі REPL.&
і |
регулярні оператори і може бути перевантажено, в той час як and
і or
викувані на мову (хоча спеціальний метод для примусу до булеву може мати побічні ефекти).
and
і or
повернути значення операнда замість True
або False
. Це не змінює значення булевих виразів в умовах - 1 or True
це 1
, але 1
це правда, теж. Але колись він використовувався для емуляції умовного оператора ( cond ? true_val : false_val
у синтаксисі С, 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)
Підказка є в назві:
Хоча можливо і справді іноді бажано (зазвичай з міркувань ефективності) виконувати логічні операції з побітовими операторами, вам, як правило, слід уникати їх для таких цілей, щоб запобігти незначним помилкам та небажаним побічним ефектам.
Якщо вам потрібно маніпулювати бітами, тоді побітові оператори створені спеціально. Книга розваг: Hackers Delight містить декілька цікавих і справді корисних прикладів того, чого можна досягти за допомогою дрібниць.
Загальним правилом є використання відповідного оператора для існуючих операндів. Використовуйте логічні (логічні) оператори з логічними операндами та побітові оператори з (ширшими) інтегральними операндами (примітка: False еквівалентно 0 , а True до 1 ). Єдиним "хитрим" сценарієм є застосування логічних операторів до небулевих операндів.
Давайте розглянемо простий приклад, як описано в [SO]: Python - Відмінності між «і» і «&» :5 & 7
проти 5 and 7
прогнозу .
Для побітового та ( & ), все досить просто:
5 = 0b101
7 = 0b111
-----------------
5 & 7 = 0b101 = 5
Для логічного та , ось що [Python.Docs]: Булеві операційні стани ( наголос на мені):
(Зверніть увагу , що ні і , ні або обмежувати значення і типу вони повертаються до Помилковому і правдивому , а повернути останній оцінений аргумент .
Приклад :
>>> 5 and 7
7
>>> 7 and 5
5
Звичайно, те саме стосується | проти або .
Логічні операції - це логічні операції.
Побітові операції - це операції над двійковими бітами.
Побітові операції:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
Операції:
&
: 1, якщо обидва біти дорівнюють 1, інакше 0|
: 1, якщо будь-який біт дорівнює 1, інакше 0^
: 1, якщо біти різні, 0, якщо вони однакові~
': Переверніть кожен бітДеякі способи використання побітових операцій:
Логічні операції:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
Логічні "та" проти побітових "&":
Псевдокод / 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:
# Do something ...
Це означає, що якщо обидві умови ( a==2
і b>10
) є істинними одночасно, тоді можна виконати тіло умовного оператора.
використовуються для обробки та вилучення даних. Наприклад, якщо ви хочете витягти чотири LSB (Найменші значущі біти) цілого числа, ви можете зробити це:
p & 0xF