Comment obtenir le contraire (négation) d'un booléen en Python?

98

Pour l'exemple suivant:

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

Existe-t-il un moyen de sauter la deuxième instruction if? Juste pour dire à l'ordinateur de renvoyer l'opposé du booléen bool?

Amyassin
la source
6
Ceci est probablement juste pseudocode, mais intet boolsont les deux noms de BUILTIN (pour les types qu'ils représentent), et ne doit pas être utilisé comme noms de variables.
SingleNegationElimination
oui, c'est juste un pseudo-code, à des fins de démonstration uniquement ...
amyassin
6
if x == True:devrait être écrit if x:.
Mike Graham du

Réponses:

170

Vous pouvez simplement utiliser:

return not bool
jtbandes
la source
4
En outre, int in range (....)est inefficace. Il créera une liste puis effectuera une recherche linéaire. Mieux que ce x in range(low, high)n'est low <= x < high.
MRAB
48

L' notopérateur (négation logique)

La meilleure façon est probablement d'utiliser l'opérateur not:

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

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

Donc au lieu de votre code:

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

Vous pouvez utiliser:

return not bool

La négation logique comme fonction

Il y a aussi deux fonctions dans le operatormodule operator.not_et son alias operator.__not__au cas où vous en auriez besoin comme fonction plutôt que comme opérateur:

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

Ceux-ci peuvent être utiles si vous souhaitez utiliser une fonction qui nécessite une fonction de prédicat ou un rappel.

Par exemple mapou 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]

Bien entendu, la même chose pourrait également être obtenue avec une lambdafonction équivalente :

>>> my_not_function = lambda item: not item

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

N'utilisez pas l'opérateur d'inversion au niveau du bit ~sur les booléens

On pourrait être tenté d'utiliser l'opérateur d'inversion au niveau du bit ~ou la fonction d'opérateur équivalente operator.inv(ou l'un des 3 autres alias là-bas). Mais comme boolune sous-classe du intrésultat peut être inattendue car elle ne renvoie pas le "booléen inverse", il renvoie le "entier inverse":

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

C'est parce que Trueéquivaut à 1et Falseà 0et que l'inversion au niveau du bit fonctionne sur la représentation au niveau du bit des entiers 1 et 0.

Donc, ceux-ci ne peuvent pas être utilisés pour "nier" un bool.

Négation avec les tableaux NumPy (et sous-classes)

Si vous avez affaire à des tableaux NumPy (ou des sous-classes comme pandas.Seriesou pandas.DataFrame) contenant des booléens, vous pouvez en fait utiliser l'opérateur inverse au niveau du bit ( ~) pour annuler tous les booléens d'un tableau:

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

Ou la fonction NumPy équivalente:

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

Vous ne pouvez pas utiliser l' notopérateur ou la operator.notfonction sur les tableaux NumPy car ceux-ci exigent que ceux-ci retournent un seul bool(pas un tableau de booléens), cependant NumPy contient également une fonction logique non qui fonctionne élément par élément:

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

Cela peut également être appliqué aux tableaux non booléens:

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

Personnaliser vos propres classes

notfonctionne en appelant boolla valeur et annule le résultat. Dans le cas le plus simple, la valeur de vérité appellera simplement __bool__l'objet.

Ainsi, en implémentant __bool__(ou __nonzero__en Python 2), vous pouvez personnaliser la valeur de vérité et donc le résultat de 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)

J'ai ajouté une printdéclaration afin que vous puissiez vérifier qu'elle appelle vraiment la méthode:

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

De même, vous pouvez implémenter la __invert__méthode pour implémenter le comportement lorsqu'il ~est appliqué:

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)

Encore une fois avec un printappel pour voir qu'il est effectivement appelé:

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

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

Cependant, une __invert__telle implémentation pourrait être déroutante car son comportement est différent du comportement Python "normal". Si jamais vous faites cela, documentez-le clairement et assurez-vous qu'il a un cas d'utilisation assez bon (et commun).

MSeifert
la source
11

Python a un opérateur "pas", non? N'est-ce pas simplement "non"? Un péché,

  return not bool
Patrick87
la source
3

Vous pouvez simplement comparer le tableau booléen. Par exemple

X = [True, False, True]

puis

Y = X == False

te donnerait

Y = [False, True, False]
Sébastien
la source
1
Pour un tableau Numpy, peut-être, mais pour une liste Python standard, c'est incorrect. Puisque le PO ne mentionne pas non plus, je ne vois pas comment cela répond à la question.
SiHa
3

La réponse acceptée ici est la plus correcte pour le scénario donné.

Cela m'a fait me demander comment inverser simplement une valeur booléenne en général. Il s'avère que la solution acceptée ici fonctionne comme une seule doublure, et il y en a une autre qui fonctionne également. En supposant que vous ayez une variable "n" que vous savez être un booléen, les moyens les plus simples de l'inverser sont:

n = n is False

qui était ma solution originale, puis la réponse acceptée à cette question:

n = not n

Ce dernier est plus clair, mais je me suis posé des questions sur les performances et je l'ai exploré timeit- et il s'avère que n = not nc'est aussi le moyen PLUS RAPIDE d'inverser la valeur booléenne.

user1411616
la source
2

Si vous essayez d'implémenter une bascule , de sorte que chaque fois que vous réexécutez un code persistant, il est annulé, vous pouvez le faire comme suit:

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

L'exécution de ce code définira d'abord le toggleà Trueet à chaque fois que cet extrait de code sera appelé, la bascule sera annulée.

user1767754
la source