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

PythonBoolean

Python Problem Overview


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?

Python Solutions


Solution 1 - Python

To negate a boolean, you can use the not operator:

not bool

Or in your case, the if/return blocks can be replaced by:

return not bool

Be sure to note the operator precedence rules, and the negated is and in operators: a is not b and a not in b.

Solution 2 - Python

The not operator (logical negation)

Probably the best way is using the operator 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

The logical negation as function

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:

>>> 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:

>>> 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:

>>> my_not_function = lambda item: not item

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

Do not use the bitwise invert operator ~ on booleans

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":

>>> ~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.

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

Negation with NumPy arrays (and subclasses)

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:

>>> 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:

>>> 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])

Customizing your own classes

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.

So by implementing __bool__ (or __nonzero__ in Python 2) you can customize the truth value and thus the result of 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:

>>> 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:

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:

>>> 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.

Solution 3 - Python

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

  return not bool

Solution 4 - Python

The accepted answer here is the most correct for the given scenario.

It made me wonder though about simply inverting a boolean value in general. It turns out the accepted solution here works as one liner, and there's another one-liner that works as well. Assuming you have a variable "n" that you know is a boolean, the easiest ways to invert it are:

n = n is False

which was my original solution, and then the accepted answer from this question:

n = not n

The latter IS more clear, but I wondered about performance and hucked it through timeit - and it turns out at n = not n is also the FASTER way to invert the boolean value.

Solution 5 - Python

Python has not operator to reverse the boolean value.

Examples:

If you can want to reverse the value in the return statement, use like below code.

return not bool

If you can want to reverse the value in the if condition, use like below code

if not bool:
	return True
else:
	return False

If you can want to reverse the value when passing the value to the method level, use like below code

check(not bool)

If you can want to reverse the value when assigning the value, use like below code.

key = not bool

Solution 6 - Python

You can just compare the boolean array. For example

X = [True, False, True]

then

Y = X == False

would give you

Y = [False, True, False]

Solution 7 - Python

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.

Solution 8 - Python

Another way to achieve the same outcome, which I found useful for a pandas dataframe.

As suggested below by mousetail:

bool(1 - False)

bool(1 - True)

Solution 9 - Python

I think the most compact version is

> self.foobar ^= True

Which does not require repeating the whole name and works with pure booleans.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionamyassinView Question on Stackoverflow
Solution 1 - PythonjtbandesView Answer on Stackoverflow
Solution 2 - PythonMSeifertView Answer on Stackoverflow
Solution 3 - PythonPatrick87View Answer on Stackoverflow
Solution 4 - PythonInduaneView Answer on Stackoverflow
Solution 5 - PythonSathiaView Answer on Stackoverflow
Solution 6 - PythonSebastianView Answer on Stackoverflow
Solution 7 - Pythonuser1767754View Answer on Stackoverflow
Solution 8 - PythonCandideView Answer on Stackoverflow
Solution 9 - PythonAmoView Answer on Stackoverflow