logical - python conditional operator
Operadores booleanos vs operadores bitwise (8)
Aquí hay otra diferencia, que me dejó perplejo por un tiempo: porque &
(y otros operadores bit a bit) tienen una precedencia mayor que and
(y otros operadores booleanos) las siguientes expresiones evalúan valores diferentes:
0 < 1 & 0 < 2
versus
0 < 1 and 0 < 2
A saber, el primero produce False
ya que es equivalente a 0 < (1 & 0) < 2
, por lo tanto 0 < 0 < 2
, por lo tanto 0 < 0 and 0 < 2
.
Estoy confundido en cuanto a cuándo debería usar un Boolean vs operadores Bitwise
and vs &, or vs |
¿Podría alguien aclararme cuándo debo usar cada uno y cuándo usar uno sobre el otro afectará mis resultados?
Aquí hay un par de pautas:
- Los operadores booleanos se usan generalmente en valores booleanos , pero los operadores bit a bit se usan generalmente en valores enteros .
- Los operadores booleanos están en cortocircuito pero los operadores bit a bit no están en cortocircuito.
El comportamiento de cortocircuito es útil en expresiones como esta:
if x is not None and x.foo == 42:
# ...
Esto no funcionaría correctamente con el operador bit a bit ya que ambos lados siempre se evaluarían, dando AttributeError: ''NoneType'' object has no attribute ''foo''
. Cuando usa el booleano and
operador, la segunda expresión no se evalúa cuando la primera es False. De manera similar or
no evalúa el segundo argumento si el primero es Verdadero.
En teoría, yy or
vienen directamente de la lógica booleana (y por lo tanto operan en dos booleanos para producir un booleano), mientras que &
y |
aplica el booleano y / o a los bits individuales de los enteros. Aquí hay muchas preguntas sobre cómo funciona el último exactamente.
Aquí hay diferencias prácticas que pueden afectar sus resultados:
-
and
/or
cortocircuito, es decir,True or sys.exit(1)
no saldrá, porque para un cierto valor (True or ...
,False and ...
) del primer operando, el segundo no cambiaría el resultado = no necesita ser evaluado. Pero|
y no cortocircuitar -True | sys.exit(1)
True | sys.exit(1)
te saca del REPL. - (Solo se aplica a algunos idiomas con sobrecarga de operadores, incluidos Python :)
&
y|
son operadores regulares y pueden estar sobrecargados -and
/or
están forjados en el lenguaje (aunque al menos en Python, el método especial de coerción para booleano puede tener efectos secundarios). - (solo se aplica a algunos idiomas [consulte el comentario de KennyTM] :) yy
or
devuelva (¿siempre ?, nunca lo entiendo realmente, ni lo necesitaba) el valor de un operando en lugar deTrue
oFalse
. Esto no cambia el significado de las expresiones booleanas en condiciones -1 or True
es1
, pero1
es verdadero. Pero una vez se usó para emular un operador condicional (cond ? true_val : false_val
en sintaxis C,true_val if cond else false_val
en Python desde hace algunos años). Para&
y|
, el tipo de resultado depende de cómo los operandos sobrecargan los respectivos métodos especiales (True & False
esFalse
,99 & 7
es3
, para conjuntos es uniones / intersección ...).
Pero incluso cuando, por ejemplo, a_boolean & another_boolean
funcionarían de manera idéntica, la solución correcta es using and
- simplemente porque and
y están asociados con la expresión y condición booleana mientras &
y |
representan un poco de twiddling.
La operación booleana son operaciones lógicas.
Las operaciones bit a bit son operaciones en bits binarios.
Operaciones bit a bit:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
Las operaciones:
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
Algunos de los usos de las operaciones bit a bit:
1) Configuración y borrado de bits
Operaciones Booleanas:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
La pista está en el nombre:
- Los operadores booleanos son para realizar operaciones lógicas (pruebas de verdad comunes en programación y lógica formal)
- Los operadores bit a bit son para "mezclar bit" (manipulación de bits de bajo nivel en tipos de datos numéricos y de bytes)
Si bien es posible y, de hecho, a veces deseable (por razones de eficiencia) realizar operaciones lógicas con operadores bit a bit, en general, debe evitarlos para tales fines para evitar errores sutiles y efectos secundarios no deseados.
Si necesita manipular bits, entonces los operadores bit a bit se construyen a propósito. El libro de la diversión: Hackers Delight contiene algunos ejemplos geniales y genuinamente útiles de lo que se puede lograr con el intercambio de bits.
La regla general es usar el operador apropiado para los operandos existentes. Utilice operadores booleanos (lógicos) con operandos booleanos, y operadores bit a bit con operandos integrales (más amplios) (nota: False
es equivalente a 0 , y True
a 1 ). El único escenario "engañoso" es aplicar operadores booleanos a operandos no booleanos.
Tomemos un ejemplo simple, como se describe en [SO]: Python - Diferencias entre ''y'' y ''&'' [duplicado] : 5 & 7
contra 5 and 7
.
Para bitwise y ( &
), las cosas son bastante sencillas:
5 = 0b101 7 = 0b111 ----------------- 5 & 7 = 0b101 = 5
Para lo lógico y , esto es lo que [Python]: estados de operaciones booleanos :
(Tenga en cuenta que ni ni ni or restringe el valor y el tipo regresan a
False
yTrue
, sino que devuelve el último argumento evaluado .
Ejemplo :
>>> 5 and 7 7 >>> 7 and 5 5
Por supuesto, lo mismo aplica para |
contra or
.
Si está intentando hacer operaciones booleanas con elementos en numpy
, la respuesta es algo diferente. Puedes usar &
y |
para operaciones booleanas de elementos, pero and
y devolverá el error de valor.
Para estar seguro, puede usar las funciones de lógica 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)
Boolean ''y'' contra Bitwise ''y'':
Pseudo-código / Python me ayudó a entender la diferencia entre estos:
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)