web-dev-qa-db-fra.com

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

Pour l'échantillon 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 retourner l'opposé du booléen bool?

64
amyassin

Vous pouvez simplement utiliser:

return not bool
120
jtbandes

L'opérateur not (négation logique)

Le meilleur moyen 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 en tant que fonction

Le module operatoroperator.not_ et c'est 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

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

Par exemple map ou 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 être obtenue avec une fonction équivalente lambda:

>>> 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 binaire inversé ~ ou la fonction opérateur équivalente operator.inv (ou l’un des trois autres alias présents). Mais comme bool est une sous-classe de int, le résultat pourrait être inattendu, car il ne renvoie pas le "booléen inverse", il renvoie le "entier inverse":

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

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

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

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

Si vous utilisez des tableaux NumPy (ou des sous-classes comme pandas.Series ou pandas.DataFrame) contenant des booléens, vous pouvez utiliser l’opérateur inverse au niveau du bit (~) pour nier 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'opérateur not ou le operator.not fonction sur les tableaux NumPy car ceux-ci exigent que ceux-ci renvoient un seul bool (et non un tableau de booléens), cependant, NumPy contient également une fonction logique not qui fonctionne élément par élément:

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

Cela peut aussi s'appliquer aux tableaux non booléens:

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

Personnaliser vos propres cours

not fonctionne en appelant bool sur la valeur et en annulant le résultat. Dans le cas le plus simple, le valeur de vérité appellera simplement __bool__ sur l'objet.

Donc, en mettant en œuvre __bool__ (ou __nonzero__ dans 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 instruction print 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 le __invert__ méthode pour implémenter le comportement quand ~ 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 appel print pour voir qu'il s'appelle réellement:

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

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

Cependant, implémenter __invert__ comme cela pourrait être déroutant parce que son comportement est différent du comportement "normal" Python. Si vous le faites clairement, documentez-le et assurez-vous qu'il a une utilisation assez bonne (et courante) -Cas.

19
MSeifert

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

  return not bool
9
Patrick87

Si vous essayez d'implémenter un bascule, de sorte que chaque fois que vous réexécutez un code persistant annulé, vous pouvez y parvenir comme suit:

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

L'exécution de ce code définira d'abord toggle sur True et chaque fois que cet extrait sera appelé, le basculement sera annulé.

2
user1767754