Im Allgemeinen ist 'someobj is None' 'someobj == None' vorzuziehen
Aaron Maenpaa
Was ist mit Pseudocode, wenn X nicht None ist? Oder X != None?
Charlie Parker
Diese Frage ist ausführlicher als die anderen ... Lob ...
Alamin
Antworten:
187
Im ersten Test versucht Python, das Objekt in einen boolWert zu konvertieren, falls dies noch nicht geschehen ist. Grob fragen wir das Objekt: Sind Sie bedeutungsvoll oder nicht? Dies erfolgt mit dem folgenden Algorithmus:
Wenn das Objekt über eine __nonzero__spezielle Methode verfügt (wie auch über numerische integrierte Funktionen intund float), wird diese Methode aufgerufen. Es muss entweder einen boolWert zurückgeben, der dann direkt verwendet wird, oder einen intWert, der berücksichtigt wird, Falsewenn er gleich Null ist.
Andernfalls, wenn das Objekt eine hat __len__spezielle Methode (wie auch Behälter Einbauten, list, dict, set, tuple, ...), ist es diese Methode aufruft, einen Behälter unter Berücksichtigung , Falsewenn es leer ist (Länge ist null).
Andernfalls wird das Objekt berücksichtigt, es Truesei denn, Nonein diesem Fall wird es berücksichtigt False.
Im zweiten Test wird das Objekt auf Gleichheit mit verglichen None. Hier fragen wir das Objekt: "Sind Sie diesem anderen Wert gleich?" Dies erfolgt mit dem folgenden Algorithmus:
Wenn das Objekt eine __eq__Methode hat, wird es aufgerufen, und der Rückgabewert wird dann in einen boolWert konvertiert und verwendet, um das Ergebnis der zu bestimmen if.
Andernfalls wird das Objekt __cmp__aufgerufen , wenn es über eine Methode verfügt. Diese Funktion muss eine Rückgabe intder Reihenfolge der beiden Objekte zurückgeben ( -1if self < other, 0if self == other, +1if self > other).
Andernfalls wird das Objekt auf Identität verglichen (dh es bezieht sich auf dasselbe Objekt, wie vom isBediener getestet werden kann ).
Mit dem isBediener ist ein weiterer Test möglich . Wir würden das Objekt fragen: "Sind Sie dieses bestimmte Objekt?"
Im Allgemeinen würde ich empfehlen, den ersten Test mit nicht numerischen Werten zu verwenden, den Test auf Gleichheit zu verwenden, wenn Sie Objekte derselben Art (zwei Zeichenfolgen, zwei Zahlen, ...) vergleichen und nur dann auf Identität prüfen möchten Verwenden von Sentinel-Werten ( Nonedh nicht initialisiert für ein Mitgliedsfeld, zum Beispiel oder bei Verwendung der getattroder der __getitem__Methoden).
Obwohl technisch korrekt, erklärt dies nicht, dass Tupel, Listen, Dikte, Strs, Unicodes, Ints, Floats usw. ungleich Null sind . Es ist weitaus üblicher, sich auf den Wahrheitswert des eingebauten Typs zu verlassen, als sich auf eine benutzerdefinierte Methode ungleich Null zu verlassen .
ddaa
50
Dies sind eigentlich beide schlechte Praktiken. Es war einmal in Ordnung, None und False beiläufig als ähnlich zu behandeln. Seit Python 2.2 ist dies jedoch nicht die beste Richtlinie.
Wenn Sie einen if xoder eine if not xArt Test durchführen, muss Python zunächst implizit xin einen Booleschen Wert konvertieren . Die Regeln für die boolFunktion beschreiben eine Reihe von Dingen, die falsch sind; alles andere ist wahr. Wenn der Wert von x anfangs nicht richtig boolesch war, ist diese implizite Konvertierung nicht wirklich die klarste Art, Dinge zu sagen.
Vor Python 2.2 gab es keine Bool-Funktion, daher war es noch weniger klar.
Zweitens sollten Sie nicht wirklich mit testen == None. Sie sollten is Noneund verwenden 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 toNone 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!
Wie viele Singletons gibt es? Five: None, True, False, NotImplementedund Ellipsis. Da es wirklich unwahrscheinlich ist, dass Sie NotImplementedoder verwenden Ellipsis, und Sie würden es niemals sagen if x is True(weil es einfach if xviel klarer ist), werden Sie immer nur testen None.
Die zweite Form ist kategorisch keine schlechte Praxis. PEP 8 empfiehlt die Verwendung von if x zweimal . Zuerst für Sequenzen (anstatt len zu verwenden) und dann für True und False (anstatt is zu verwenden). Praktisch jeder Python-Code, den ich gesehen habe, verwendet if x und wenn nicht x.
Antti Rasinen
35
Denn es Noneist nicht das einzige, was als falsch angesehen wird.
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, (), [], {}Und ""sind alle unterschiedlich None, so dass Ihre beiden Code - Snippets sind nicht gleichwertig.
Beachten Sie außerdem Folgendes:
>>>False==0True>>>False==()False
if object:ist keine Gleichstellungsprüfung. 0, (), [], None, {}, Usw. sind alle verschieden voneinander, aber sie alle zu bewerten auf False.
Dies ist die "Magie" hinter kurzschließenden Ausdrücken wie:
In Bezug auf Ihre letzte Frage sind sie gleichwertig.
Sylvain Defresne
Und beide falsch, weil "" falsch ist. Der zweite sollte '("",) oder ("s",)' lauten. Wie auch immer, moderne Versionen von Python haben einen richtigen ternären Operator. Dieser fehleranfällige Hack sollte verbannt werden.
die __nonzero__ Methode von Spam wird aufgerufen. Aus dem Python-Handbuch:
__nonzero__ ( self ) Wird aufgerufen, um das Testen von Wahrheitswerten und die integrierte Operation bool () zu implementieren. sollte False oder True oder ihre ganzzahligen Entsprechungen 0 oder 1 zurückgeben. Wenn diese Methode nicht definiert ist, wird __len __ () aufgerufen, wenn sie definiert ist (siehe unten). Wenn eine Klasse weder __len __ () noch __nonzero __ () definiert, werden alle ihre Instanzen als wahr betrachtet.
Wenn du fragst
if spam ==None:print"Sorry. No SPAM here either."
die __eq__ Methode von Spam wird mit dem Argument genannt None .
Diese beiden Vergleiche dienen unterschiedlichen Zwecken. Der erste prüft auf den booleschen Wert von etwas, der zweite prüft auf Identität mit dem Wert None.
Um absolut korrekt zu sein, prüft die zweite auf Gleichheit mit dem Wert None ... "someobj is None" prüft auf Identität.
Matthew Trevor
0
Zum einen ist das erste Beispiel kürzer und sieht besser aus. Wie in den anderen Beiträgen, hängt Ihre Auswahl auch davon ab, was Sie wirklich mit dem Vergleich machen möchten.
Persönlich habe ich einen konsistenten Ansatz für alle Sprachen gewählt: Ich mache if (var)(oder gleichwertig) nur, wenn var als boolesch deklariert ist (oder als solches definiert ist, haben wir in C keinen bestimmten Typ). Ich stelle diesen Variablen sogar ein b(so wäre es bVartatsächlich) voran, um sicherzugehen, dass ich hier nicht versehentlich einen anderen Typ verwende.
Ich mag implizites Casting nicht wirklich in Boolesche Werte, noch weniger, wenn es zahlreiche komplexe Regeln gibt.
Natürlich werden die Leute anderer Meinung sein. Einige gehen weiter, ich sehe if (bVar == true)im Java-Code bei meiner Arbeit (zu redundant für meinen Geschmack!), Andere lieben zu viel kompakte Syntax, gehen while (line = getNextLine())(zu mehrdeutig für mich).
X != None
?Antworten:
Im ersten Test versucht Python, das Objekt in einen
bool
Wert zu konvertieren, falls dies noch nicht geschehen ist. Grob fragen wir das Objekt: Sind Sie bedeutungsvoll oder nicht? Dies erfolgt mit dem folgenden Algorithmus:Wenn das Objekt über eine
__nonzero__
spezielle Methode verfügt (wie auch über numerische integrierte Funktionenint
undfloat
), wird diese Methode aufgerufen. Es muss entweder einenbool
Wert zurückgeben, der dann direkt verwendet wird, oder einenint
Wert, der berücksichtigt wird,False
wenn er gleich Null ist.Andernfalls, wenn das Objekt eine hat
__len__
spezielle Methode (wie auch Behälter Einbauten,list
,dict
,set
,tuple
, ...), ist es diese Methode aufruft, einen Behälter unter Berücksichtigung ,False
wenn es leer ist (Länge ist null).Andernfalls wird das Objekt berücksichtigt, es
True
sei denn,None
in diesem Fall wird es berücksichtigtFalse
.Im zweiten Test wird das Objekt auf Gleichheit mit verglichen
None
. Hier fragen wir das Objekt: "Sind Sie diesem anderen Wert gleich?" Dies erfolgt mit dem folgenden Algorithmus:Wenn das Objekt eine
__eq__
Methode hat, wird es aufgerufen, und der Rückgabewert wird dann in einenbool
Wert konvertiert und verwendet, um das Ergebnis der zu bestimmenif
.Andernfalls wird das Objekt
__cmp__
aufgerufen , wenn es über eine Methode verfügt. Diese Funktion muss eine Rückgabeint
der Reihenfolge der beiden Objekte zurückgeben (-1
ifself < other
,0
ifself == other
,+1
ifself > other
).Andernfalls wird das Objekt auf Identität verglichen (dh es bezieht sich auf dasselbe Objekt, wie vom
is
Bediener getestet werden kann ).Mit dem
is
Bediener ist ein weiterer Test möglich . Wir würden das Objekt fragen: "Sind Sie dieses bestimmte Objekt?"Im Allgemeinen würde ich empfehlen, den ersten Test mit nicht numerischen Werten zu verwenden, den Test auf Gleichheit zu verwenden, wenn Sie Objekte derselben Art (zwei Zeichenfolgen, zwei Zahlen, ...) vergleichen und nur dann auf Identität prüfen möchten Verwenden von Sentinel-Werten (
None
dh nicht initialisiert für ein Mitgliedsfeld, zum Beispiel oder bei Verwendung dergetattr
oder der__getitem__
Methoden).Zusammenfassend haben wir:
quelle
Dies sind eigentlich beide schlechte Praktiken. Es war einmal in Ordnung, None und False beiläufig als ähnlich zu behandeln. Seit Python 2.2 ist dies jedoch nicht die beste Richtlinie.
Wenn Sie einen
if x
oder eineif not x
Art Test durchführen, muss Python zunächst implizitx
in einen Booleschen Wert konvertieren . Die Regeln für diebool
Funktion beschreiben eine Reihe von Dingen, die falsch sind; alles andere ist wahr. Wenn der Wert von x anfangs nicht richtig boolesch war, ist diese implizite Konvertierung nicht wirklich die klarste Art, Dinge zu sagen.Vor Python 2.2 gab es keine Bool-Funktion, daher war es noch weniger klar.
Zweitens sollten Sie nicht wirklich mit testen
== None
. Sie solltenis None
und verwendenis not None
.Siehe PEP 8, Style Guide für Python-Code .
Wie viele Singletons gibt es? Five:
None
,True
,False
,NotImplemented
undEllipsis
. Da es wirklich unwahrscheinlich ist, dass SieNotImplemented
oder verwendenEllipsis
, und Sie würden es niemals sagenif x is True
(weil es einfachif x
viel klarer ist), werden Sie immer nur testenNone
.quelle
Denn es
None
ist nicht das einzige, was als falsch angesehen wird.False
,0
,()
,[]
,{}
Und""
sind alle unterschiedlichNone
, so dass Ihre beiden Code - Snippets sind nicht gleichwertig.Beachten Sie außerdem Folgendes:
if object:
ist keine Gleichstellungsprüfung.0
,()
,[]
,None
,{}
, Usw. sind alle verschieden voneinander, aber sie alle zu bewerten auf False.Dies ist die "Magie" hinter kurzschließenden Ausdrücken wie:
Das ist eine Abkürzung für:
obwohl du wirklich schreiben solltest:
quelle
PEP 8 - Style Guide für Python Code empfiehlt die Verwendung von is oder is, wenn Sie auf None-ness testen
Wenn Sie jedoch auf mehr als None-ness testen, sollten Sie den booleschen Operator verwenden.
quelle
Wenn du fragst
die __nonzero__ Methode von Spam wird aufgerufen. Aus dem Python-Handbuch:
Wenn du fragst
die __eq__ Methode von Spam wird mit dem Argument genannt None .
Weitere Informationen zu den Anpassungsmöglichkeiten finden Sie in der Python-Dokumentation unter https://docs.python.org/reference/datamodel.html#basic-customization
quelle
Diese beiden Vergleiche dienen unterschiedlichen Zwecken. Der erste prüft auf den booleschen Wert von etwas, der zweite prüft auf Identität mit dem Wert None.
quelle
Zum einen ist das erste Beispiel kürzer und sieht besser aus. Wie in den anderen Beiträgen, hängt Ihre Auswahl auch davon ab, was Sie wirklich mit dem Vergleich machen möchten.
quelle
Die Antwort lautet "es kommt darauf an".
Ich verwende das erste Beispiel, wenn ich 0, "", [] und False (Liste nicht erschöpfend) in diesem Zusammenhang als gleichwertig mit None betrachte.
quelle
Persönlich habe ich einen konsistenten Ansatz für alle Sprachen gewählt: Ich mache
if (var)
(oder gleichwertig) nur, wenn var als boolesch deklariert ist (oder als solches definiert ist, haben wir in C keinen bestimmten Typ). Ich stelle diesen Variablen sogar einb
(so wäre esbVar
tatsächlich) voran, um sicherzugehen, dass ich hier nicht versehentlich einen anderen Typ verwende.Ich mag implizites Casting nicht wirklich in Boolesche Werte, noch weniger, wenn es zahlreiche komplexe Regeln gibt.
Natürlich werden die Leute anderer Meinung sein. Einige gehen weiter, ich sehe
if (bVar == true)
im Java-Code bei meiner Arbeit (zu redundant für meinen Geschmack!), Andere lieben zu viel kompakte Syntax, gehenwhile (line = getNextLine())
(zu mehrdeutig für mich).quelle