Как получить противоположное (отрицание) логического значения в Python? - PullRequest
59 голосов
/ 11 августа 2011

Для следующего примера:

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

Есть ли способ пропустить второй оператор if?Просто сказать компьютеру вернуть противоположное логическое значение bool?

Ответы [ 5 ]

117 голосов
/ 11 августа 2011

Вы можете просто использовать:

return not bool
17 голосов
/ 01 июля 2018

Оператор 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

Это может быть полезно, если вы хотите использовать функцию, для которой требуется функция предиката или обратный вызов.

Например map или 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]

Конечно, того же можно достичь с помощью эквивалентной функции 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])

Вы не можете использовать оператор not или функцию operator.not в массивах NumPy, потому что они требуют, чтобы они возвращали один bool (не массив логических значений), однако NumPy также содержит логическую функцию not, которая работает с элементом -wise:

>>> 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 значения и отменяет результат. В простейшем случае значение true просто вызовет __bool__ для объекта.

Таким образом, реализовав __bool__ (или __nonzero__ в Python 2), вы можете настроить значение истинности и, следовательно, результат 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. Если вы когда-нибудь сделаете это, четко документируйте это и убедитесь, что у него довольно хороший (и распространенный) вариант использования.

9 голосов
/ 11 августа 2011

В Python есть оператор not, верно? Разве это не просто "нет"? Как в,

  return not bool
2 голосов
/ 30 мая 2018

Если вы пытаетесь реализовать переключатель , чтобы при каждом повторном запуске постоянного кода, который был отменен, вы можете добиться этого следующим образом:

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

Запуск этого кода сначала установит toggle в True, и каждый раз, когда вызывается этот фрагмент, переключение будет отменено.

0 голосов
/ 01 октября 2017

Вы можете просто сравнить логический массив.Например,

X = [True, False, True]

, тогда

Y = X == False

даст вам

Y = [False, True, False]
...