Reputation: 2983
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
?
Upvotes: 221
Views: 477453
Reputation: 118671
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
.
Upvotes: 352
Reputation: 149
I think the most compact version is
self.foobar ^= True
Which does not require repeating the whole name and works with pure booleans.
Upvotes: 4
Reputation: 9
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)
Upvotes: 0
Reputation: 2042
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.
Upvotes: 7
Reputation: 152637
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
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.
>>> 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]
~
on booleansOne 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
.
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])
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.
Upvotes: 116
Reputation: 25094
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.
Upvotes: 2
Reputation: 67
You can just compare the boolean array. For example
X = [True, False, True]
then
Y = X == False
would give you
Y = [False, True, False]
Upvotes: 3
Reputation: 28292
Python has a "not" operator, right? Is it not just "not"? As in,
return not bool
Upvotes: 12