Probablemente la mejor forma sea utilizando el operador not
:
>>> value = True
>>> not value
False
>>> value = False
>>> not value
True
Entonces, en lugar de tu código:
if bool == True:
return False
else:
return True
Podrías usar:
return not bool
La negación lógica como función
También hay dos funciones en el operator
módulo operator.not_
y su alias operator.__not__
en caso de que lo necesite como función en lugar de como operador:
>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False
Estos pueden ser útiles si desea utilizar una función que requiere una función de predicado o una devolución de llamada.
Por ejemplo map
o filter
:
>>> lst = [True, False, True, False]
>>> list(map(operator.not_, lst))
[False, True, False, True]
>>> lst = [True, False, True, False]
>>> list(filter(operator.not_, lst))
[False, False]
Por supuesto, también se podría lograr lo mismo con una lambda
función equivalente :
>>> my_not_function = lambda item: not item
>>> list(map(my_not_function, lst))
[False, True, False, True]
No utilice el operador de inversión bit a bit ~
en valores booleanos
Uno podría tener la tentación de usar el operador de inversión bit a bit ~
o la función de operador equivalente operator.inv
(o uno de los otros 3 alias allí). Pero debido a que bool
es una subclase del int
resultado que podría ser inesperado porque no devuelve el "booleano inverso", devuelve el "entero inverso":
>>> ~True
-2
>>> ~False
-1
Eso es porque True
es equivalente a 1
y False
a 0
e inversión a nivel de bits opera en la representación bit a bit de los números enteros 1
y 0
.
Por tanto, estos no se pueden utilizar para "negar" a bool
.
Negación con matrices (y subclases) NumPy
Si está tratando con matrices NumPy (o subclases como pandas.Series
o pandas.DataFrame
) que contienen booleanos, en realidad puede usar el operador inverso bit a bit ( ~
) para negar todos los booleanos en una matriz:
>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False, True, False, True])
O la función NumPy equivalente:
>>> np.bitwise_not(arr)
array([False, True, False, True])
No puede usar el not
operador o la operator.not
función en arreglos NumPy porque estos requieren que estos devuelvan un solo bool
(no un arreglo de valores booleanos), sin embargo, NumPy también contiene una función no lógica que funciona por elementos:
>>> np.logical_not(arr)
array([False, True, False, True])
Eso también se puede aplicar a matrices no booleanas:
>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False, True])
Personalizando tus propias clases
not
funciona invocando bool
el valor y niega el resultado. En el caso más simple, el valor de verdad simplemente llamará __bool__
al objeto.
Entonces, al implementar __bool__
(o __nonzero__
en Python 2) puede personalizar el valor de verdad y, por lo tanto, el resultado de not
:
class Test(object):
def __init__(self, value):
self._value = value
def __bool__(self):
print('__bool__ called on {!r}'.format(self))
return bool(self._value)
__nonzero__ = __bool__
def __repr__(self):
return '{self.__class__.__name__}({self._value!r})'.format(self=self)
Agregué una print
declaración para que pueda verificar que realmente llama al método:
>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False
Del mismo modo, podría implementar el __invert__
método para implementar el comportamiento cuando ~
se aplica:
class Test(object):
def __init__(self, value):
self._value = value
def __invert__(self):
print('__invert__ called on {!r}'.format(self))
return not self._value
def __repr__(self):
return '{self.__class__.__name__}({self._value!r})'.format(self=self)
Nuevamente con una print
llamada para ver que realmente se llama:
>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False
>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True
Sin embargo, implementarlo __invert__
así podría resultar confuso porque su comportamiento es diferente del comportamiento "normal" de Python. Si alguna vez lo hace, documente claramente y asegúrese de que tenga un caso de uso bastante bueno (y común).
int
ybool
son los dos nombres incorporados (para los tipos que representan), y no se debe utilizar como nombres de variables.