问题:如何在Python中获得布尔值的相反(否定)?

对于以下示例:

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

有什么办法可以跳过第二个if语句?只是为了告诉计算机返回布尔值的相反值bool

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?


回答 0

您可以使用:

return not bool

You can just use:

return not bool

回答 1

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(或那里的其他三个别名之一)。但是由于结果bool的子类int可能是意外的,因为它不返回“反布尔”,而是返回“反整数”:

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

这是因为,True就相当于1False0和位反转上的按位表示操作整数 10

因此,这些不能用于“否定” a 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])

自定义自己的Class

not通过调用bool值并取反结果来工作。在最简单的情况下,真值将仅调用__bool__对象。

因此,通过实现(或在Python 2中),您可以自定义true值,从而自定义结果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

同样,您可以实现应用方法以在~应用时实现行为:

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行为。如果您这样做的话,请清楚地记录下来,并确保它有一个很好的(和常见的)用例。

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


回答 2

Python有一个“非”运​​算符,对吗?不仅仅是“不是”吗?如

  return not bool

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

  return not bool

回答 3

您可以只比较布尔数组。例如

X = [True, False, True]

然后

Y = X == False

会给你

Y = [False, True, False]

You can just compare the boolean array. For example

X = [True, False, True]

then

Y = X == False

would give you

Y = [False, True, False]

回答 4

对于给定的情况,此处可接受的答案是最正确的。

但是,这使我想知道一般只将布尔值取反。事实证明,这里公认的解决方案可以用作一种衬板,而另一种衬板也可以使用。假设您有一个已知为布尔值的变量“ n”,那么将其取反的最简单方法是:

n = n is False

这是我最初的解决方案,然后是这个问题的公认答案:

n = not n

后者更清晰,但是我想知道性能,并一直坚持下去timeit-事实证明,n = not n这也是反转布尔值的更快方法。

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.


回答 5

如果您尝试实现一个toggle,那么无论何时只要重新运行一个持久化的代码,它都会被否定,则可以实现以下目标:

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

运行此代码将首先将设置为toggleTrue并且每当此代码段调用时,切换都会被取消。

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.


声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。