如何在Python中获取布尔值的反值?

211 投票
8 回答
427702 浏览
提问于 2025-04-16 23:24

对于下面这个例子:

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

有没有什么办法可以跳过第二个if语句?就是说告诉计算机返回布尔值bool的反面?

8 个回答

12

Python确实有一个“not”运算符,对吧?它不就是“not”吗?就像这样,

  return not bool
110

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

这些在你想用需要谓词函数或回调的函数时会很有用。

比如 mapfilter

>>> 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(或者其他三个别名)。但是因为 boolint 的子类,结果可能会让人意外,因为它返回的不是“布尔值的反”,而是“整数的反”:

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

这是因为 True 相当于 1,而 False 相当于 0,位取反操作是在整数 10 的位表示上进行的。

所以这些不能用来“取反”一个 bool

使用 NumPy 数组(及其子类)进行取反

如果你在处理包含布尔值的 NumPy 数组(或像 pandas.Seriespandas.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 行为不同。如果你真的这样做了,请清楚地记录下来,并确保它有一个相当好的(且常见的)使用场景。

332

要对一个布尔值(就是只有真和假两种状态的值)取反,你可以使用 not 操作符

not bool

在你的例子中,ifreturn 的部分可以用以下方式替代:

return not bool

记得注意 操作符的优先级规则,还有取反的 isin 操作符:a is not ba not in b

撰写回答