How do I get the opposite (negation) of a Boolean in Python?


How do I get the opposite (negation) of a Boolean in Python?



For the following sample:


def fuctionName(int, bool):
if int in range(...):
if bool == True:
return False
else:
return True



Is there any way to skip the second if-statement? Just to tell the computer to return the opposite of the boolean bool?


bool





This is probably just pseudocode, but int and bool are both builtin names (for the types they represent), and should not be used as variable names.
– SingleNegationElimination
Aug 11 '11 at 18:19


int


bool





yes, it's just a pseudo-code ,, demonstration purposes only...
– amyassin
Aug 11 '11 at 18:26






if x == True: should be written if x:.
– Mike Graham
Aug 11 '11 at 18:57


if x == True:


if x:




5 Answers
5



You can just use:


return not bool





Also, int in range (....) is inefficient. It will create a list and then perform a linear search. Better than x in range(low, high) is low <= x < high.
– MRAB
Aug 11 '11 at 19:24


int in range (....)


x in range(low, high)


low <= x < high





@MRAB: even with Python 3?
– Neil G
Aug 12 '11 at 22:02





@Neil G: No, I think it should be OK in Python 3, but as the above code could be either, it's safer to err on the side of caution. :-)
– MRAB
Aug 13 '11 at 0:06





@MRAB: You're right.
– Neil G
Aug 13 '11 at 1:17





@amyassin: MRAB meant that low <= x < high is better than x in range(low, high). int in range(....) was supposed to indicate the same thing as x in range(low, high).
– jtbandes
Aug 13 '11 at 18:47


low <= x < high


x in range(low, high)


int in range(....)


x in range(low, high)



Python has a "not" operator, right? Is it not just "not"? As in,


return not bool


not



Probably the best way is using the operator not:


not


>>> value = True
>>> not value
False

>>> value = False
>>> not value
True



So instead of your code:


if bool == True:
return False
else:
return True



You could use:


return not bool



There are also two functions in the operator module operator.not_ and it's alias operator.__not__ in case you need it as function instead of as operator:


operator


operator.not_


operator.__not__


>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False



These can be useful if you want to use a function that requires a predicate-function or a callback.



For example map or filter:


map


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]



Of course the same could also be achieved with an equivalent lambda function:


lambda


>>> my_not_function = lambda item: not item

>>> list(map(my_not_function, lst))
[False, True, False, True]


~



One might be tempted to use the bitwise invert operator ~ or the equivalent operator function operator.inv (or one of the other 3 aliases there). But because bool is a subclass of int the result could be unexpected because it doesn't return the "inverse boolean", it returns the "inverse integer":


~


operator.inv


bool


int


>>> ~True
-2
>>> ~False
-1



That's because True is equivalent to 1 and False to 0 and bitwise inversion operates on the bitwise representation of the integers 1 and 0.


True


1


False


0


1


0



So these cannot be used to "negate" a bool.


bool



If you're dealing with NumPy arrays (or subclasses like pandas.Series or pandas.DataFrame) containing booleans you can actually use the bitwise inverse operator (~) to negate all booleans in an array:


pandas.Series


pandas.DataFrame


~


>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False, True, False, True])



Or the equivalent NumPy function:


>>> np.bitwise_not(arr)
array([False, True, False, True])



You cannot use the not operator or the operator.not function on NumPy arrays because these require that these return a single bool (not an array of booleans), however NumPy also contains a logical not function that works element-wise:


not


operator.not


bool


>>> np.logical_not(arr)
array([False, True, False, True])



That can also be applied to non-boolean arrays:


>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False, True])



not works by calling bool on the value and negate the result. In the simplest case the truth value will just call __bool__ on the object.


not


bool


__bool__



So by implementing __bool__ (or __nonzero__ in Python 2) you can customize the truth value and thus the result of not:


__bool__


__nonzero__


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__ # Python 2 compatibility

def __repr__(self):
return '{self.__class__.__name__}({self._value!r})'.format(self=self)



I added a print statement so you can verify that it really calls the method:


print


>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False



Likewise you could implement the __invert__ method to implement the behavior when ~ is applied:


__invert__


~


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)



Again with a print call to see that it is actually called:


print


>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False

>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True



However implementing __invert__ like that could be confusing because it's behavior is different from "normal" Python behavior. If you ever do that clearly document it and make sure that it has a pretty good (and common) use-case.


__invert__



If you are trying to implement a toggle, so that anytime you re-run a persistent code its being negated, you can achieve that as following:


try:
toggle = not toggle
except NameError:
toggle = True



Running this code will first set the toggle to True and anytime this snippet ist called, toggle will be negated.


toggle


True



You can just compare the boolean array. For example


X = [True, False, True]



then


Y = X == False



would give you


Y = [False, True, False]





For a Numpy array, maybe, but for a standard Python list, this is incorrect. Since the OP does not mention either, I fail to see how this answers the question.
– SiHa
Oct 1 '17 at 12:37






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask

NSwag: Generate C# Client from multiple Versions of an API