Wie bekomme ich das Gegenteil (Negation) eines Booleschen Werts in Python?

93

Für das folgende Beispiel:

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

Gibt es eine Möglichkeit, die zweite if-Anweisung zu überspringen? Nur um dem Computer zu sagen, dass er das Gegenteil des Booleschen Wertes zurückgeben soll bool?

Amyassin
quelle
6
Dies ist wahrscheinlich nur Pseudo - Code, aber intund boolsind beide builtin Namen (für die Typen sie repräsentieren), und sollten nicht als Variablennamen verwendet werden.
SingleNegationElimination
Ja, es ist nur ein Pseudocode, nur zu Demonstrationszwecken ...
Amyassin
6
if x == True:sollte geschrieben werden if x:.
Mike Graham

Antworten:

162

Sie können einfach verwenden:

return not bool
jtbandes
quelle
4
Auch int in range (....)ist ineffizient. Es wird eine Liste erstellt und anschließend eine lineare Suche durchgeführt. Besser als es x in range(low, high)ist low <= x < high.
MRAB
47

Der notOperator (logische Negation)

Der wahrscheinlich beste Weg ist die Verwendung des Operators not:

>>> value = True
>>> not value
False

>>> value = False
>>> not value
True

Also anstelle Ihres Codes:

if bool == True:
    return False
else:
    return True

Du könntest benutzen:

return not bool

Die logische Negation als Funktion

Es gibt auch zwei Funktionen im operatorModul operator.not_und es ist ein Alias, operator.__not__falls Sie es als Funktion anstatt als Operator benötigen:

>>> import operator
>>> operator.not_(False)
True
>>> operator.not_(True)
False

Diese können nützlich sein, wenn Sie eine Funktion verwenden möchten, die eine Prädikatfunktion oder einen Rückruf erfordert.

Zum Beispiel mapoder 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]

Das gleiche könnte natürlich auch mit einer äquivalenten lambdaFunktion erreicht werden:

>>> my_not_function = lambda item: not item

>>> list(map(my_not_function, lst))
[False, True, False, True]

Verwenden Sie den bitweisen Invertierungsoperator nicht ~für Boolesche Werte

Man könnte versucht sein, den bitweisen Invertierungsoperator ~oder die entsprechende Operatorfunktion operator.inv(oder einen der anderen 3 Aliase dort) zu verwenden. Da booljedoch eine Unterklasse des intErgebnisses unerwartet sein kann, weil sie nicht den "inversen Booleschen Wert" zurückgibt, gibt sie die "inverse Ganzzahl" zurück:

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

Das liegt daran , Trueentspricht 1und Falseauf 0und bitweise Inversion arbeitet auf der bitweise Darstellung der ganzen Zahlen 1 und 0.

Diese können also nicht verwendet werden, um a zu "negieren" bool.

Negation mit NumPy-Arrays (und Unterklassen)

Wenn Sie mit NumPy-Arrays (oder Unterklassen wie pandas.Seriesoder pandas.DataFrame) arbeiten, die Boolesche Werte enthalten, können Sie den bitweisen inversen Operator ( ~) verwenden, um alle Booleschen Werte in einem Array zu negieren :

>>> import numpy as np
>>> arr = np.array([True, False, True, False])
>>> ~arr
array([False,  True, False,  True])

Oder die entsprechende NumPy-Funktion:

>>> np.bitwise_not(arr)
array([False,  True, False,  True])

Sie können den notOperator oder die operator.notFunktion nicht für NumPy-Arrays verwenden, da diese erfordern, dass diese ein einzelnes bool(kein Array von Booleschen Werten) zurückgeben. NumPy enthält jedoch auch eine logische Nicht-Funktion, die elementweise funktioniert:

>>> np.logical_not(arr)
array([False,  True, False,  True])

Dies kann auch auf nicht-boolesche Arrays angewendet werden:

>>> arr = np.array([0, 1, 2, 0])
>>> np.logical_not(arr)
array([ True, False, False,  True])

Anpassen Ihrer eigenen Klassen

notfunktioniert, indem boolder Wert aufgerufen und das Ergebnis negiert wird. Im einfachsten Fall ruft der Wahrheitswert nur __bool__das Objekt auf.

Durch die Implementierung __bool__(oder __nonzero__in Python 2) können Sie den Wahrheitswert und damit das Ergebnis von 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)

Ich habe eine printAnweisung hinzugefügt , damit Sie überprüfen können, ob die Methode wirklich aufgerufen wird:

>>> a = Test(10)
>>> not a
__bool__ called on Test(10)
False

Ebenso können Sie die __invert__Methode implementieren, um das Verhalten zu implementieren, wenn ~es angewendet wird:

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)

Nochmals mit einem printAnruf, um zu sehen, dass es tatsächlich heißt:

>>> a = Test(True)
>>> ~a
__invert__ called on Test(True)
False

>>> a = Test(False)
>>> ~a
__invert__ called on Test(False)
True

Eine __invert__solche Implementierung kann jedoch verwirrend sein, da sich das Verhalten vom "normalen" Python-Verhalten unterscheidet. Wenn Sie dies jemals tun, dokumentieren Sie es klar und stellen Sie sicher, dass es einen ziemlich guten (und allgemeinen) Anwendungsfall hat.

MSeifert
quelle
11

Python hat einen "nicht" -Operator, oder? Ist es nicht nur "nicht"? Wie in,

  return not bool
Patrick87
quelle
3

Sie können einfach das boolesche Array vergleichen. Beispielsweise

X = [True, False, True]

dann

Y = X == False

würde dir geben

Y = [False, True, False]
Sebastian
quelle
1
Für ein Numpy-Array vielleicht, aber für eine Standard-Python-Liste ist dies falsch. Da das OP auch nicht erwähnt, sehe ich nicht, wie dies die Frage beantwortet.
SiHa
2

Wenn Sie versuchen, einen Umschalter zu implementieren , damit ein persistenter Code, der erneut ausgeführt wird, negiert wird, können Sie dies wie folgt erreichen:

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

Wenn Sie diesen Code ausführen, wird zuerst das toggleauf gesetzt , Trueund jedes Mal, wenn dieses Snippet aufgerufen wird, wird das Umschalten negiert.

user1767754
quelle
2

Die hier akzeptierte Antwort ist die richtige für das gegebene Szenario.

Ich habe mich allerdings gefragt, ob ich einen Booleschen Wert im Allgemeinen einfach invertieren soll. Es stellt sich heraus, dass die hier akzeptierte Lösung als ein Liner funktioniert, und es gibt einen anderen Einzeiler, der ebenfalls funktioniert. Angenommen, Sie haben eine Variable "n", von der Sie wissen, dass sie ein Boolescher Wert ist, können Sie sie am einfachsten invertieren:

n = n is False

Das war meine ursprüngliche Lösung und dann die akzeptierte Antwort auf diese Frage:

n = not n

Letzteres ist klarer, aber ich habe mich über die Leistung gewundert und sie durchgeknallt timeit- und es stellt sich heraus, dass dies n = not nauch die SCHNELLERE Möglichkeit ist, den Booleschen Wert umzukehren.

user1411616
quelle