Y a-t-il une différence entre « foo is None » et « foo == None » ?
-
09-06-2019 - |
Question
Y a-t-il une différence entre :
if foo is None: pass
et
if foo == None: pass
La convention que j'ai vue dans la plupart du code Python (et dans le code que j'écris moi-même) est la première, mais je suis récemment tombé sur du code qui utilise la seconde.Aucun n'est une instance (et la seule instance, IIRC) de NoneType, donc cela ne devrait pas avoir d'importance, n'est-ce pas ?Y a-t-il des circonstances dans lesquelles cela pourrait se produire ?
La solution
is
revient toujours True
s'il compare la même instance d'objet
Alors que ==
est finalement déterminé par le __eq__()
méthode
c'est à dire.
>>> class Foo(object):
def __eq__(self, other):
return True
>>> f = Foo()
>>> f == None
True
>>> f is None
False
Autres conseils
Vous voudrez peut-être lire ceci identité et équivalence de l'objet.
L'instruction 'is' est utilisée pour l'identité des objets, elle vérifie si les objets font référence à la même instance (même adresse en mémoire).
Et l'instruction '==' fait référence à l'égalité (même valeur).
Un mot d'avertissement:
if foo:
# do something
Est pas exactement la même que:
if x is not None:
# do something
Le premier est un test de valeur booléenne et peut être évalué comme faux dans différents contextes.Il y a un certain nombre de choses qui représentent faux dans les tests de valeurs booléennes, par exemple des conteneurs vides, des valeurs booléennes.Aucun n'est également évalué comme faux dans cette situation, mais d'autres choses le sont également.
(ob1 is ob2)
égal à (id(ob1) == id(ob2))
La raison foo is None
est la méthode préférée, c'est que vous manipulez peut-être un objet qui définit son propre __eq__
, et cela définit l'objet comme étant égal à None.Alors, utilisez toujours foo is None
si tu as besoin de voir si c'est effectivement le cas None
.
Il n’y a pas de différence car les objets identiques seront bien sûr égaux.Cependant, PPE 8 indique clairement que vous devez utiliser is
:
Les comparaisons avec des singletons comme None doivent toujours être effectuées avec is ou is not, jamais avec les opérateurs d'égalité.
is
tests d'identité, pas égalité.Pour votre déclaration foo is none
, Python compare simplement l'adresse mémoire des objets.Cela signifie que vous posez la question « Ai-je deux noms pour le même objet ? »
==
d'autre part, des tests d'égalité déterminés par le __eq__()
méthode.Il ne se soucie pas de l'identité.
In [102]: x, y, z = 2, 2, 2.0
In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)
In [104]: x is y
Out[104]: True
In [105]: x == y
Out[105]: True
In [106]: x is z
Out[106]: False
In [107]: x == z
Out[107]: True
None
est un opérateur singleton.Donc None is None
est toujours vrai.
In [101]: None is None
Out[101]: True
Pour None, il ne devrait pas y avoir de différence entre l'égalité (==) et l'identité (est).Le NoneType renvoie probablement l'identité pour l'égalité.Puisque None est la seule instance que vous pouvez créer de NoneType (je pense que c'est vrai), les deux opérations sont les mêmes.Dans le cas d’autres types, ce n’est pas toujours le cas.Par exemple:
list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"
Cela afficherait "Égal" puisque les listes ont une opération de comparaison qui n'est pas le retour d'identité par défaut.
@Jason:
Je recommande d'utiliser quelque chose de plus dans le sens de
if foo: #foo isn't None else: #foo is None
Je n'aime pas utiliser "if foo:" à moins que foo ne représente vraiment une valeur booléenne (c'est-à-dire0 ou 1).Si foo est une chaîne, un objet ou autre chose, "if foo:" peut fonctionner, mais cela me ressemble à un raccourci paresseux.Si vous vérifiez si x est Aucun, dites "si x est Aucun :".
Quelques détails supplémentaires :
Le
is
la clause vérifie en fait si les deuxobject
Les s sont au même emplacement de mémoire ou non.c'est-à-dire s'ils pointent tous les deux vers le même emplacement de mémoire et ont le mêmeid
.En conséquence de 1,
is
garantit si, ou non, les deux lexiquement représentésobject
s ont des attributs identiques (attributs-d-attributs...) ou nonInstanciation de types primitifs comme
bool
,int
,string
(sauf quelques exceptions),NoneType
ayant la même valeur sera toujours dans le même emplacement mémoire.
Par exemple.
>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True
Et depuis NoneType
ne peut avoir qu'une seule instance de lui-même dans la table "de recherche" de python, donc le premier et le second sont davantage un style de programmation du développeur qui a écrit le code (peut-être par souci de cohérence) plutôt que d'avoir une raison logique subtile d'en choisir une sur l'autre.
La conclusion de John Machin selon laquelle None
est un singleton est une conclusion renforcée par ce code.
>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>>
Depuis None
est un singleton, x == None
et x is None
aurait le même résultat.Cependant, à mon avis esthétique, x == None
est le meilleur.
a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence
a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True