Puis-je utiliser:
if A:
au lieu de
if A is not None:
Ce dernier semble tellement verbeux. Y a-t-il une différence?
La déclaration
if A:
appellera A.__nonzero__()
(voir la documentation des noms de méthodes spéciales ) et utilisera la valeur de retour de cette fonction. Voici le résumé:
object.__nonzero__(self)
Appelé à implémenter le test de valeur de vérité et l'opération intégrée
bool()
; doit renvoyerFalse
ouTrue
, ou leurs équivalents entiers0
ou1
. Lorsque cette méthode n'est pas définie,__len__()
est appelée, si elle est définie, et l'objet est considéré comme vrai si son résultat est différent de zéro. Si une classe ne définit ni__len__()
ni__nonzero__()
, toutes ses instances sont considérées comme vraies.
D'autre part,
if A is not None:
compare uniquement la référence A
avec None
pour voir si elle est la même ou non.
A is not None
est donc plus rapide car il y a beaucoup moins de travail à faireif object(): pass
est d'environ 0,130 usec par boucle, tandis que d'if object() is not None: pass
environ 0,135 usec. Quoi qu'il en soit, vous ne devriez pas utiliser les performances pour choisir entre ces deux, mais plutôt regarder les différences dans leur fonctionnement, car elles ne sont pas équivalentes .if A is not None
semble être plus lent car il s'agit d'une comparaison et doit charger le singleton intégréNone
comme étape intermédiaire avec laquelle comparerA
(jetez un œil audis.dis()
). Corrigez-moi si je me trompe maisif A:
semble être plus efficace, dès que vous voulez vraiment tester la valeur de vérité et non l'None
identité.python -m timeit -s"a=0" "if a: pass" "else: pass"
est plus rapide quepython -m timeit -s"a=0" "if a is None: pass" "else: pass"
maispython -m timeit -s"a=1" "if a: pass" "else: pass"
est plus lent. Peut-être dépendant de la plate-forme, voyez si vous obtenez les mêmes résultatsis None
test était en effet le plus lent pour moi. En pypy, ils mesuraient tous exactement la même chose :)Comme écrit dans PEP8 :
la source
None
, mais juste par une vérification de la valeur de vérité. Dans ce cas, celaif A:
semble plus efficace (prenez adis.dis()
, il y a les étapes supplémentaires de chargement du builtinNone
et de comparaison, avecif A is not None:
, alors qu'il n'y en a qu'unjump_if
dans l'autre cas).donc ce n'est pas la même chose que
la source
De nombreuses fonctions renvoient None s'il n'y a pas de résultats appropriés. Par exemple, la
.first()
méthode d' une requête SQLAlchemy renvoie None s'il n'y avait aucune ligne dans le résultat. Supposons que vous sélectionniez une valeur susceptible de renvoyer 0 et que vous ayez besoin de savoir si elle est réellement 0 ou si la requête n'a donné aucun résultat.Un idiome courant est de donner à l'argument facultatif d'une fonction ou d'une méthode la valeur par défaut None, puis de tester cette valeur étant None pour voir si elle a été spécifiée. Par exemple:
comparez cela à:
Dans ce dernier, que se passe-t-il si vous appelez
spam(0)
ouspam([])
? La fonction détecte (à tort) que vous n'avez pas transmis de valeur poureggs
et calcule une valeur par défaut pour vous. Ce n'est probablement pas ce que vous voulez.Ou imaginez une méthode comme "retourner la liste des transactions pour un compte donné". Si le compte n'existe pas, il peut renvoyer None. Ceci est différent de renvoyer une liste vide (ce qui signifierait que "ce compte existe mais n'a pas enregistré de transactions).
Enfin, revenons à la base de données. Il y a une grande différence entre NULL et une chaîne vide. Une chaîne vide indique généralement "il y a une valeur ici, et cette valeur n'est rien du tout". NULL indique que "cette valeur n'a pas été saisie."
Dans chacun de ces cas, vous voudriez utiliser
if A is None
. Vous recherchez une valeur spécifique - Aucune - pas seulement "toute valeur qui se trouve être convertie en False".la source
Ils font des choses très différentes .
Les contrôles ci - dessous si A a quelque chose à l' exception des valeurs
False
,[]
,None
,''
et0
. Il vérifie la valeur de A.Ce qui suit vérifie si A est un objet différent de None. Il vérifie et compare la référence (adresse mémoire) de A et None.
MISE À JOUR: Explication supplémentaire
Souvent, les deux semblent faire la même chose, donc beaucoup de gens les utilisent de manière interchangeable - c'est une très mauvaise idée. La raison pour laquelle les deux donnent les mêmes résultats est souvent par pure coïncidence due à des optimisations de l'interpréteur / compilateur comme l' internement ou autre chose.
Avec ces optimisations à l'esprit, les entiers et les chaînes de même valeur finissent par utiliser le même espace mémoire. Cela explique probablement pourquoi deux chaînes distinctes agissent comme si elles étaient identiques.
Cependant, d'autres choses ne se comportent pas de la même manière.
Les deux listes ont clairement leur propre mémoire. Étonnamment, les tuples se comportent comme des chaînes.
C'est probablement parce que les tuples sont garantis de ne pas changer, il est donc logique de réutiliser la même mémoire.
En bout de ligne, vous ne pouvez pas vous fier aux coïncidences . Ce n'est pas parce que ça caque comme un canard que c'est un canard. Utilisez
is
et en==
fonction de ce que vous voulez vraiment vérifier. Ces choses peuvent être difficiles à déboguer car seis
lit comme de la prose que nous passons souvent en revue.la source
None
est un singleton, ce n'est pas un détail d'implémentation (contrairement à int ou string interning). Je ne suis pas sûr de comprendre ce que tu veux dire.None
se comporte différemmentint
ou enstr
raison de l'internement. Mon point est queis
et==
vérifie des choses différentes; vérifie d'abord une adresse mémoire, le second vérifie le contenu des adresses mémoire.if A:
se révélera faux si A vaut 0, Faux, chaîne vide, liste vide ou Aucun, ce qui peut conduire à des résultats indésirables.la source
La plupart des guides que j'ai vus suggèrent que vous devriez utiliser
si un:
sauf si vous avez une raison d'être plus précis.
Il y a quelques légères différences. Il existe des valeurs autres que None qui renvoient False, par exemple des listes vides ou 0, alors réfléchissez à ce que vous testez réellement.
la source
None est une valeur spéciale en Python qui désigne généralement une variable non initialisée. Pour tester si A n'a pas cette valeur particulière, utilisez:
Les valeurs Falsey sont une classe spéciale d'objets en Python (par exemple, false, []). Pour tester si A est faux, utilisez:
Ainsi, les deux expressions ne sont pas les mêmes et vous feriez mieux de ne pas les traiter comme des synonymes.
PS None est également faux, donc la première expression implique la seconde. Mais la seconde couvre d'autres valeurs fausses en plus de None. Maintenant ... si vous pouvez être sûr que vous ne pouvez pas avoir d'autres valeurs fausses en plus de None dans A, alors vous pouvez remplacer la première expression par la seconde.
la source
Ça dépend du contexte.
J'utilise
if A:
quand je m'attendsA
à être une sorte de collection, et je veux seulement exécuter le bloc si la collection n'est pas vide. Cela permet à l'appelant de passer n'importe quelle collection bien comportée, vide ou non, et de lui faire faire ce que j'attends. Il permet égalementNone
etFalse
de supprimer l'exécution du bloc, ce qui est parfois pratique pour appeler du code.OTOH, si je m'attends
A
à être un objet complètement arbitraire mais qu'il aurait pu être défini par défautNone
, alors je l' utilise toujoursif A is not None
, car le code d'appel aurait pu délibérément passer une référence à une collection vide, une chaîne vide ou un type numérique de valeur 0, ou booléenFalse
, ou une instance de classe qui se trouve être fausse dans un contexte booléen.Et d'un autre côté, si je m'attends
A
à être quelque chose de plus spécifique (par exemple, une instance d'une classe dont je vais appeler des méthodes), mais cela aurait pu être défini par défautNone
, et je considère la conversion booléenne par défaut comme un propriété de la classe Cela ne me dérange pas d'appliquer à toutes les sous-classes, alors je vais simplement utiliserif A:
pour sauver mes doigts le terrible fardeau de taper 12 caractères supplémentaires.la source
J'ai créé un fichier appelé
test.py
et l' ai exécuté sur l'interpréteur. Vous pouvez changer ce que vous voulez, pour vérifier avec certitude comment les choses se passent dans les coulisses.C'est la différence de l'assembleur:
La source:
la source
Le premier est plus pythonique (meilleur code idéomatique), mais n'exécutera pas le bloc si A est faux (et non aucun).
la source
is/is not None
. Après PEP8 est Pythonic. D'ailleurs les deux tests sont différents .python> = 2,6,
si nous écrivons comme
générera un avertissement comme,
Nous pouvons donc utiliser
la source