如何在Python中获取布尔值的反值?
对于下面这个例子:
def fuctionName(int, bool):
if int in range(...):
if bool == True:
return False
else:
return True
有没有什么办法可以跳过第二个if语句?就是说告诉计算机返回布尔值bool
的反面?
8 个回答
Python确实有一个“not”运算符,对吧?它不就是“not”吗?就像这样,
return not bool
not
最简单的方法是使用 not
操作符:
>>> value = True
>>> not value
False
>>> value = False
>>> not value
True
所以,替代你的代码:
if bool == True:
return False
else:
return True
你可以使用:
return not bool
作为函数的逻辑取反
在 operator
模块中,还有两个函数 operator.not_
和它的别名 operator.__not__
,如果你需要把它当作函数使用而不是操作符:
>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False
这些在你想用需要谓词函数或回调的函数时会很有用。
>>> 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]
当然,也可以用一个等效的 lambda
函数来实现:
>>> my_not_function = lambda item: not item
>>> list(map(my_not_function, lst))
[False, True, False, True]
不要在布尔值上使用位取反操作符 ~
可能会有人想用位取反操作符 ~
或等效的操作符函数 operator.inv
(或者其他三个别名)。但是因为 bool
是 int
的子类,结果可能会让人意外,因为它返回的不是“布尔值的反”,而是“整数的反”:
>>> ~True
-2
>>> ~False
-1
这是因为 True
相当于 1
,而 False
相当于 0
,位取反操作是在整数 1 和 0 的位表示上进行的。
所以这些不能用来“取反”一个 bool
。
使用 NumPy 数组(及其子类)进行取反
如果你在处理包含布尔值的 NumPy 数组(或像 pandas.Series
或 pandas.DataFrame
这样的子类),你实际上可以使用位取反操作符(~
)来对数组中的所有布尔值进行取反:
>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False, True, False, True])
或者使用等效的 NumPy 函数:
>>> np.bitwise_not(arr)
array([False, True, False, True])
你不能在 NumPy 数组上使用 not
操作符或 operator.not
函数,因为这些要求返回一个单一的 bool
(而不是布尔值数组),不过 NumPy 也包含一个逐元素工作的逻辑取反函数:
>>> np.logical_not(arr)
array([False, True, False, True])
这也可以应用于非布尔数组:
>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False, True])
自定义你的类
not
通过对值调用 bool
并取反结果来工作。在最简单的情况下,真值将直接调用对象的 __bool__
方法。
所以通过实现 __bool__
(在 Python 2 中是 __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)
我添加了一个 print
语句,这样你可以验证它确实调用了这个方法:
>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False
同样,你也可以实现 __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)
同样加上一个 print
调用,看看它是否真的被调用:
>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False
>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True
不过像这样实现 __invert__
可能会让人困惑,因为它的行为与“正常”的 Python 行为不同。如果你真的这样做了,请清楚地记录下来,并确保它有一个相当好的(且常见的)使用场景。
要对一个布尔值(就是只有真和假两种状态的值)取反,你可以使用 not
操作符:
not bool
在你的例子中,if
和 return
的部分可以用以下方式替代:
return not bool
记得注意 操作符的优先级规则,还有取反的 is
和 in
操作符:a is not b
和 a not in b
。