Généralement, 'someobj is None' est préférable à 'someobj == None'
Aaron Maenpaa
qu'en est-il du pseudocode si X n'est pas None? Ou X != None?
Charlie Parker
cette question est plus verbeuse que les autres ... bravo ...
alamin
Réponses:
187
Dans le premier test, Python essaie de convertir l'objet en une boolvaleur s'il n'en est pas déjà une. En gros, nous demandons à l'objet: êtes-vous significatif ou non? Cela se fait à l'aide de l'algorithme suivant:
Si l'objet a une __nonzero__méthode spéciale (comme le font les intégrés numériques, intet float), il appelle cette méthode. Il doit soit renvoyer une boolvaleur qui est alors directement utilisée, soit une intvaleur considérée Falsesi égale à zéro.
Dans le cas contraire, si l'objet a une __len__méthode spéciale (comme les conteneurs Encastrements, list, dict, set, tuple, ...), il appelle cette méthode, compte tenu d' un récipient Falsesi elle est vide (longueur est égale à zéro).
Sinon, l'objet est considéré à Truemoins que ce ne soit le Nonecas auquel cas, il est considéré False.
Dans le deuxième test, l’égalité de l’objet est comparée à None. Ici, nous demandons à l'objet: "Êtes-vous égal à cette autre valeur?" Cela se fait à l'aide de l'algorithme suivant:
Si l'objet a une __eq__méthode, il est appelé et la valeur de retour est ensuite convertie en boolvaleur et utilisée pour déterminer le résultat du if.
Sinon, si l'objet a une __cmp__méthode, il est appelé. Cette fonction doit renvoyer un intindiquant l'ordre des deux objets ( -1si self < other, 0si self == other, +1si self > other).
Sinon, les objets sont comparés pour l'identité (c'est-à-dire qu'ils font référence au même objet, comme cela peut être testé par l' isopérateur).
Il existe un autre test possible en utilisant l' isopérateur. Nous demanderions à l'objet: "Êtes-vous cet objet particulier?"
De manière générale, je recommanderais d'utiliser le premier test avec des valeurs non numériques, d'utiliser le test d'égalité lorsque vous souhaitez comparer des objets de même nature (deux chaînes, deux nombres, ...) et de vérifier l'identité uniquement lorsque en utilisant des valeurs sentinelles ( Nonec'est-à-dire non initialisé pour un champ membre par exemple, ou lors de l'utilisation getattrdes __getitem__méthodes ou ).
Bien que techniquement correct, cela n'explique pas que les tuples, listes, dicts, strs, unicodes, ints, floats, etc. aient une valeur non nulle . Il est beaucoup plus courant de s'appuyer sur la valeur de vérité du type intégré que de s'appuyer sur une méthode personnalisée différente de zéro .
ddaa le
50
Ce sont en fait deux mauvaises pratiques. Il était une fois, il était considéré comme acceptable de traiter avec désinvolture None et False comme similaires. Cependant, depuis Python 2.2, ce n'est pas la meilleure politique.
Premièrement, lorsque vous effectuez un test if xou un if not xtype de test, Python doit implicitement se convertir xen booléen. Les règles de la boolfonction décrivent une série de choses qui sont fausses; tout le reste est vrai. Si la valeur de x n'était pas correctement booléenne au départ, cette conversion implicite n'est pas vraiment la façon la plus claire de dire les choses.
Avant Python 2.2, il n'y avait pas de fonction booléenne, donc c'était encore moins clair.
Deuxièmement, vous ne devriez pas vraiment tester avec == None. Vous devez utiliser is Noneet is not None.
-Comparisons to singletons like None should always be done with'is'or'is not', never the equality operators.Also, beware of writing "if x" when you really mean "if x is not None"-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value.The other value might have a type
(such as a container) that could be false in a boolean context!
Combien y a-t-il de singletons? Cinq: None, True, False, NotImplementedet Ellipsis. Comme il est peu probable que vous utilisiez NotImplementedou Ellipsis, et que vous ne diriez jamaisif x is True (parce que if xc'est beaucoup plus clair), vous ne testerez jamais None.
La deuxième forme n'est catégoriquement pas une mauvaise pratique. PEP 8 recommande d'utiliser if x deux fois . D'abord pour les séquences (au lieu d'utiliser len), puis pour True et False (au lieu d'utiliser is). Pratiquement tout le code Python que j'ai vu utilise if x et sinon x.
Antti Rasinen
35
Parce que ce Nonen'est pas la seule chose qui est considérée comme fausse.
ifnotFalse:print"False is false."ifnot0:print"0 is false."ifnot[]:print"An empty list is false."ifnot():print"An empty tuple is false."ifnot{}:print"An empty dict is false."ifnot"":print"An empty string is false."
False, 0, (), [], {}Et ""sont toutes différentes None, de sorte que vos deux extraits de code sont pas équivalents.
De plus, considérez ce qui suit:
>>>False==0True>>>False==()False
if object:n'est pas un contrôle d'égalité. 0, (), [], None, {}, Etc. sont tous différents les uns des autres, mais ils ont tous évaluent à Faux.
C'est la "magie" derrière les expressions de court-circuit comme:
Concernant votre dernière question, elles sont équivalentes.
Sylvain Defresne
Et les deux sont incorrects car "" est faux. Le second devrait lire '("",) ou ("s",)'. Quoi qu'il en soit, les versions modernes de python ont un opérateur ternaire approprié. Ce hack sujet aux erreurs doit être banni.
la méthode __nonzero__ de spam est appelée. À partir du manuel Python:
__nonzero__ ( self ) Appelé pour implémenter le test de la valeur de vérité et l'opération intégrée bool (); doit renvoyer False ou True, ou leurs équivalents entiers 0 ou 1. Lorsque cette méthode n'est pas définie, __len __ () est appelée, si elle est définie (voir ci-dessous). Si une classe ne définit ni __len __ () ni __nonzero __ (), toutes ses instances sont considérées comme vraies.
Si vous demandez
if spam ==None:print"Sorry. No SPAM here either."
la méthode __eq__ de spam est appelée avec l'argument None .
Ces deux comparaisons servent des objectifs différents. Le premier vérifie la valeur booléenne de quelque chose, le second vérifie l'identité avec la valeur None.
Pour être absolument correct, le second vérifie -equality- avec une valeur None ... "someobj is None" vérifie l'identité.
Matthew Trevor
0
Pour l'un, le premier exemple est plus court et plus joli. Comme pour les autres articles, ce que vous choisissez dépend également de ce que vous voulez vraiment faire avec la comparaison.
Personnellement, j'ai choisi une approche cohérente à travers les langages: je ne fais if (var)(ou équivalent) que si var est déclaré booléen (ou défini comme tel, en C nous n'avons pas de type spécifique). Je préfixe même ces variables avec un b(donc ce serait en bVarfait) pour être sûr que je n'utiliserai pas accidentellement un autre type ici.
Je n'aime pas vraiment le cast implicite en booléen, encore moins quand il y a de nombreuses règles complexes.
Bien sûr, les gens ne seront pas d'accord. Certains vont plus loin, je vois if (bVar == true)dans le code Java à mon travail (trop redondant à mon goût!), D'autres aiment trop la syntaxe compacte, aller while (line = getNextLine())(trop ambigu pour moi).
X != None
?Réponses:
Dans le premier test, Python essaie de convertir l'objet en une
bool
valeur s'il n'en est pas déjà une. En gros, nous demandons à l'objet: êtes-vous significatif ou non? Cela se fait à l'aide de l'algorithme suivant:Si l'objet a une
__nonzero__
méthode spéciale (comme le font les intégrés numériques,int
etfloat
), il appelle cette méthode. Il doit soit renvoyer unebool
valeur qui est alors directement utilisée, soit uneint
valeur considéréeFalse
si égale à zéro.Dans le cas contraire, si l'objet a une
__len__
méthode spéciale (comme les conteneurs Encastrements,list
,dict
,set
,tuple
, ...), il appelle cette méthode, compte tenu d' un récipientFalse
si elle est vide (longueur est égale à zéro).Sinon, l'objet est considéré à
True
moins que ce ne soit leNone
cas auquel cas, il est considéréFalse
.Dans le deuxième test, l’égalité de l’objet est comparée à
None
. Ici, nous demandons à l'objet: "Êtes-vous égal à cette autre valeur?" Cela se fait à l'aide de l'algorithme suivant:Si l'objet a une
__eq__
méthode, il est appelé et la valeur de retour est ensuite convertie enbool
valeur et utilisée pour déterminer le résultat duif
.Sinon, si l'objet a une
__cmp__
méthode, il est appelé. Cette fonction doit renvoyer unint
indiquant l'ordre des deux objets (-1
siself < other
,0
siself == other
,+1
siself > other
).Sinon, les objets sont comparés pour l'identité (c'est-à-dire qu'ils font référence au même objet, comme cela peut être testé par l'
is
opérateur).Il existe un autre test possible en utilisant l'
is
opérateur. Nous demanderions à l'objet: "Êtes-vous cet objet particulier?"De manière générale, je recommanderais d'utiliser le premier test avec des valeurs non numériques, d'utiliser le test d'égalité lorsque vous souhaitez comparer des objets de même nature (deux chaînes, deux nombres, ...) et de vérifier l'identité uniquement lorsque en utilisant des valeurs sentinelles (
None
c'est-à-dire non initialisé pour un champ membre par exemple, ou lors de l'utilisationgetattr
des__getitem__
méthodes ou ).Pour résumer, nous avons:
la source
Ce sont en fait deux mauvaises pratiques. Il était une fois, il était considéré comme acceptable de traiter avec désinvolture None et False comme similaires. Cependant, depuis Python 2.2, ce n'est pas la meilleure politique.
Premièrement, lorsque vous effectuez un test
if x
ou unif not x
type de test, Python doit implicitement se convertirx
en booléen. Les règles de labool
fonction décrivent une série de choses qui sont fausses; tout le reste est vrai. Si la valeur de x n'était pas correctement booléenne au départ, cette conversion implicite n'est pas vraiment la façon la plus claire de dire les choses.Avant Python 2.2, il n'y avait pas de fonction booléenne, donc c'était encore moins clair.
Deuxièmement, vous ne devriez pas vraiment tester avec
== None
. Vous devez utiliseris None
etis not None
.Voir PEP 8, Guide de style pour le code Python .
Combien y a-t-il de singletons? Cinq:
None
,True
,False
,NotImplemented
etEllipsis
. Comme il est peu probable que vous utilisiezNotImplemented
ouEllipsis
, et que vous ne diriez jamaisif x is True
(parce queif x
c'est beaucoup plus clair), vous ne testerez jamaisNone
.la source
Parce que ce
None
n'est pas la seule chose qui est considérée comme fausse.False
,0
,()
,[]
,{}
Et""
sont toutes différentesNone
, de sorte que vos deux extraits de code sont pas équivalents.De plus, considérez ce qui suit:
if object:
n'est pas un contrôle d'égalité.0
,()
,[]
,None
,{}
, Etc. sont tous différents les uns des autres, mais ils ont tous évaluent à Faux.C'est la "magie" derrière les expressions de court-circuit comme:
qui est un raccourci pour:
bien que vous devriez vraiment écrire:
la source
PEP 8 - Guide de style pour le code Python recommande d'utiliser is ou non si vous testez None-ness
D'un autre côté, si vous testez plus de None-ness, vous devez utiliser l'opérateur booléen.
la source
Si vous demandez
la méthode __nonzero__ de spam est appelée. À partir du manuel Python:
Si vous demandez
la méthode __eq__ de spam est appelée avec l'argument None .
Pour plus d'informations sur les possibilités de personnalisation, consultez la documentation Python à https://docs.python.org/reference/datamodel.html#basic-customization
la source
Ces deux comparaisons servent des objectifs différents. Le premier vérifie la valeur booléenne de quelque chose, le second vérifie l'identité avec la valeur None.
la source
Pour l'un, le premier exemple est plus court et plus joli. Comme pour les autres articles, ce que vous choisissez dépend également de ce que vous voulez vraiment faire avec la comparaison.
la source
La réponse est "ça dépend".
J'utilise le premier exemple si je considère 0, "", [] et False (liste non exhaustive) comme équivalents à None dans ce contexte.
la source
Personnellement, j'ai choisi une approche cohérente à travers les langages: je ne fais
if (var)
(ou équivalent) que si var est déclaré booléen (ou défini comme tel, en C nous n'avons pas de type spécifique). Je préfixe même ces variables avec unb
(donc ce serait enbVar
fait) pour être sûr que je n'utiliserai pas accidentellement un autre type ici.Je n'aime pas vraiment le cast implicite en booléen, encore moins quand il y a de nombreuses règles complexes.
Bien sûr, les gens ne seront pas d'accord. Certains vont plus loin, je vois
if (bVar == true)
dans le code Java à mon travail (trop redondant à mon goût!), D'autres aiment trop la syntaxe compacte, allerwhile (line = getNextLine())
(trop ambigu pour moi).la source