Мене бентежить, коли слід використовувати булеві та побітові оператори
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