Antworten:
In Python ist das 'null'-Objekt der Singleton None.
Der beste Weg, um Dinge auf "Noneness" zu überprüfen, ist die Verwendung des Identitätsoperators is:
if foo is None:
...
None, Python ist null?Es gibt kein nullin Python, stattdessen gibt es None. Wie bereits erwähnt, besteht der genaueste Weg, um zu testen, ob etwas Noneals Wert angegeben wurde, darin, den isIdentitätsoperator zu verwenden , der testet, dass zwei Variablen auf dasselbe Objekt verweisen.
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
NoneNoneist die einzige Instanz der Klasse, NoneTypeund alle weiteren Versuche, diese Klasse zu instanziieren, geben dasselbe Objekt zurück, wodurch Noneein Singleton erstellt wird. Python-Neulinge sehen häufig Fehlermeldungen, die erwähnen NoneTypeund sich fragen, was es ist. Ich persönlich bin der Meinung, dass diese Nachrichten einfach nur namentlich erwähnt Nonewerden könnten, da sie, wie wir gleich sehen werden, Nonewenig Raum für Unklarheiten lassen. Wenn Sie also eine TypeErrorNachricht sehen, in der erwähnt wird, dass NoneTypedies nicht oder nicht möglich ist, wissen Sie einfach, dass es einfach diejenige ist None, die auf eine Weise verwendet wurde, die es nicht kann.
Ist auch Noneeine eingebaute Konstante, sobald Sie Python starten, kann sie von überall verwendet werden, egal ob in Modul, Klasse oder Funktion. NoneTypeIm Gegensatz dazu müssen Sie zuerst einen Verweis darauf erhalten, indem Sie Nonenach seiner Klasse fragen .
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
Sie können die NoneEindeutigkeit mit der Identitätsfunktion von Python überprüfen id(). Es gibt die einem Objekt zugewiesene eindeutige Nummer zurück, jedes Objekt hat eine. Wenn die ID zweier Variablen identisch ist, verweisen sie tatsächlich auf dasselbe Objekt.
>>> NoneType = type(None)
>>> id(None)
10748000
>>> my_none = NoneType()
>>> id(my_none)
10748000
>>> another_none = NoneType()
>>> id(another_none)
10748000
>>> def function_that_does_nothing(): pass
>>> return_value = function_that_does_nothing()
>>> id(return_value)
10748000
None kann nicht überschrieben werdenIn einer viel älteren Version von Python (vor 2.4) war eine Neuzuweisung möglich None, jedoch nicht mehr. Nicht einmal als Klassenattribut oder in den Grenzen einer Funktion.
# In Python 2.7
>>> class SomeClass(object):
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: cannot assign to None
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to None
# In Python 3.5
>>> class SomeClass:
... def my_fnc(self):
... self.None = 'foo'
SyntaxError: invalid syntax
>>> def my_fnc():
None = 'foo'
SyntaxError: cannot assign to keyword
Es ist daher davon auszugehen, dass alle NoneReferenzen gleich sind. Es gibt keinen "Brauch" None.
NoneVerwendung des isBedienersWenn Sie Code schreiben, könnten Sie versucht sein, wie folgt auf Noneness zu testen :
if value==None:
pass
Oder um auf solche Unwahrheiten zu testen
if not value:
pass
Sie müssen die Auswirkungen verstehen und wissen, warum es oft eine gute Idee ist, explizit zu sein.
Nonewarum das tun
value is None
eher, als
value==None
Der erste entspricht:
id(value)==id(None)
Während der Ausdruck value==Nonetatsächlich so angewendet wird
value.__eq__(None)
Wenn der Wert wirklich ist, erhalten NoneSie das, was Sie erwartet haben.
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
In den meisten Fällen ist das Ergebnis dasselbe, aber die __eq__()Methode öffnet eine Tür, die jegliche Garantie für die Genauigkeit ungültig macht, da sie in einer Klasse überschrieben werden kann, um ein spezielles Verhalten bereitzustellen.
Betrachten Sie diese Klasse.
>>> class Empty(object):
... def __eq__(self, other):
... return not other
Also probierst du es an Noneund es funktioniert
>>> empty = Empty()
>>> empty==None
True
Aber dann funktioniert es auch mit der leeren Zeichenfolge
>>> empty==''
True
Und doch
>>> ''==None
False
>>> empty is None
False
Noneals Boolescher WertDie folgenden zwei Tests
if value:
# do something
if not value:
# do something
werden in der Tat als bewertet
if bool(value):
# do something
if not bool(value):
# do something
Noneist ein "Falsey", was bedeutet, dass wenn er in einen Booleschen Wert umgewandelt wird, er zurückkehrt Falseund wenn er angewendet wird, der notOperator zurückkehrt True. Beachten Sie jedoch, dass es sich nicht nur um eine Eigenschaft handelt None. Zusätzlich zu sich Falseselbst wird die Eigenschaft von leeren Listen, Tupeln, Mengen, Diktaten, Zeichenfolgen sowie 0 und allen Objekten aus Klassen, die die zurückzugebende __bool__()magische Methode implementieren , gemeinsam genutzt False.
>>> bool(None)
False
>>> not None
True
>>> bool([])
False
>>> not []
True
>>> class MyFalsey(object):
... def __bool__(self):
... return False
>>> f = MyFalsey()
>>> bool(f)
False
>>> not f
True
Achten Sie beim Testen auf Variablen auf folgende Weise besonders darauf, was Sie in den Test einschließen oder ausschließen:
def some_function(value=None):
if not value:
value = init_value()
Wollten Sie oben aufrufen, init_value()wenn der Wert speziell auf eingestellt ist None, oder meinten Sie, dass ein auf 0oder die leere Zeichenfolge oder eine leere Liste festgelegter Wert auch die Initialisierung auslösen sollte. Wie ich schon sagte, sei achtsam. Wie so oft in Python ist explizit besser als implizit .
None in der PraxisNone als Signalwert verwendetNonehat einen besonderen Status in Python. Es ist ein beliebter Basiswert, da viele Algorithmen ihn als außergewöhnlichen Wert behandeln. In solchen Szenarien kann es als Flag verwendet werden, um zu signalisieren, dass eine Bedingung eine spezielle Behandlung erfordert (z. B. das Festlegen eines Standardwerts).
Sie können Noneden Schlüsselwortargumenten einer Funktion zuweisen und diese dann explizit testen.
def my_function(value, param=None):
if param is None:
# do something outrageous!
Sie können es als Standard zurückgeben, wenn Sie versuchen, das Attribut eines Objekts aufzurufen, und es dann explizit testen, bevor Sie etwas Besonderes tun.
value = getattr(some_obj, 'some_attribute', None)
if value is None:
# do something spectacular!
Standardmäßig wird die get()Methode eines Wörterbuchs zurückgegeben , Nonewenn versucht wird, auf einen nicht vorhandenen Schlüssel zuzugreifen:
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
Wenn Sie versuchen würden, mit der tiefgestellten Notation darauf zuzugreifen, wird a KeyErrorausgelöst
>>> value = some_dict['foo']
KeyError: 'foo'
Ebenso, wenn Sie versuchen, ein nicht vorhandenes Element zu platzieren
>>> value = some_dict.pop('foo')
KeyError: 'foo'
Dies können Sie mit einem Standardwert unterdrücken, der normalerweise auf eingestellt ist None
value = some_dict.pop('foo', None)
if value is None:
# booom!
None wird sowohl als Flag als auch als gültiger Wert verwendetDie oben beschriebenen Verwendungen von Nonegelten, wenn sie nicht als gültiger Wert angesehen werden, sondern eher als Signal, etwas Besonderes zu tun. Es gibt jedoch Situationen, in denen es manchmal wichtig ist zu wissen, woher sie Nonestammen, da sie, obwohl sie als Signal verwendet werden, auch Teil der Daten sein können.
Wenn Sie ein Objekt für seine Attribut Abfrage mit getattr(some_obj, 'attribute_name', None)zurückzubekommen NoneSie nicht sagen , ob das Attribut , das Sie zugreifen möchten , wurden eingestellt wurde Noneoder ob es überhaupt von dem Objekt nicht gefunden . Dieselbe Situation beim Zugriff auf einen Schlüssel aus einem Wörterbuch wie some_dict.get('some_key'): Sie wissen nicht, ob er some_dict['some_key']fehlt oder nur auf gesetzt ist None. Wenn Sie diese Informationen benötigen, versuchen Sie normalerweise, direkt aus einem try/exceptKonstrukt heraus auf das Attribut oder den Schlüssel zuzugreifen :
try:
# equivalent to getattr() without specifying a default
# value = getattr(some_obj, 'some_attribute')
value = some_obj.some_attribute
# now you handle `None` the data here
if value is None:
# do something here because the attribute was set to None
except AttributeError:
# we're now hanling the exceptional situation from here.
# We could assign None as a default value if required.
value = None
# In addition, since we now know that some_obj doesn't have the
# attribute 'some_attribute' we could do something about that.
log_something(some_obj)
Ähnlich mit Diktat:
try:
value = some_dict['some_key']
if value is None:
# do something here because 'some_key' is set to None
except KeyError:
# set a default
value = None
# and do something because 'some_key' was missing
# from the dict.
log_something(some_dict)
Die obigen zwei Beispiele zeigen, wie mit Objekt- und Wörterbuchfällen umgegangen wird. Was ist mit Funktionen? Das Gleiche, aber wir verwenden zu diesem Zweck das Schlüsselwortargument mit doppelten Sternchen:
def my_function(**kwargs):
try:
value = kwargs['some_key']
if value is None:
# do something because 'some_key' is explicitly
# set to None
except KeyError:
# we assign the default
value = None
# and since it's not coming from the caller.
log_something('did not receive "some_key"')
None wird nur als gültiger Wert verwendetWenn Sie feststellen, dass Ihr Code mit dem obigen try/exceptMuster übersät ist , nur um zwischen NoneFlags und NoneDaten zu unterscheiden , verwenden Sie einfach einen anderen Testwert. Es gibt ein Muster, bei dem ein Wert, der außerhalb des Satzes gültiger Werte liegt, als Teil der Daten in eine Datenstruktur eingefügt wird und zum Steuern und Testen spezieller Bedingungen (z. B. Grenzen, Status usw.) verwendet wird. Ein solcher Wert wird als Sentinel bezeichnet und kann so verwendet werden None, wie er als Signal verwendet wird. Es ist trivial, einen Sentinel in Python zu erstellen.
undefined = object()
Das undefinedobige Objekt ist einzigartig und macht nicht viel, was für ein Programm von Interesse sein könnte. Es ist daher ein hervorragender Ersatz für Noneeine Flagge. Es gelten einige Einschränkungen, mehr dazu nach dem Code.
Mit Funktion
def my_function(value, param1=undefined, param2=undefined):
if param1 is undefined:
# we know nothing was passed to it, not even None
log_something('param1 was missing')
param1 = None
if param2 is undefined:
# we got nothing here either
log_something('param2 was missing')
param2 = None
Mit Diktat
value = some_dict.get('some_key', undefined)
if value is None:
log_something("'some_key' was set to None")
if value is undefined:
# we know that the dict didn't have 'some_key'
log_something("'some_key' was not set at all")
value = None
Mit einem Objekt
value = getattr(obj, 'some_attribute', undefined)
if value is None:
log_something("'obj.some_attribute' was set to None")
if value is undefined:
# we know that there's no obj.some_attribute
log_something("no 'some_attribute' set on obj")
value = None
Wie ich bereits erwähnt habe, sind benutzerdefinierte Sentinels mit einigen Einschränkungen verbunden. Erstens sind sie keine Schlüsselwörter wie None, also schützt Python sie nicht. Sie können Ihre undefinedobigen Angaben jederzeit und an jeder Stelle im Modul überschreiben , an der sie definiert sind. Seien Sie also vorsichtig, wie Sie sie verfügbar machen und verwenden. Als nächstes ist die von zurückgegebene Instanz object()kein Singleton. Wenn Sie diesen Aufruf 10 Mal ausführen, erhalten Sie 10 verschiedene Objekte. Schließlich ist die Verwendung eines Sentinels sehr eigenwillig. Ein Sentinel ist spezifisch für die Bibliothek, in der er verwendet wird, und daher sollte sein Umfang im Allgemeinen auf die Interna der Bibliothek beschränkt sein. Es sollte nicht "auslaufen". Externer Code sollte nur dann darauf aufmerksam werden, wenn der Zweck darin besteht, die API der Bibliothek zu erweitern oder zu ergänzen.
Es heißt nicht null wie in anderen Sprachen, aber None. Es gibt immer nur eine Instanz dieses Objekts, sodass Sie die Äquivalenz mit x is None(Identitätsvergleich) überprüfen können, anstatt x == None, wenn Sie möchten.
None. Dann werden all diese klugen Leute, die sich mit ihnen vergleichen NoneType, triumphieren!
Um in Python das Fehlen eines Werts darzustellen, können Sie den Wert None ( types.NoneType.None ) für Objekte und "" (oder len () == 0 ) für Zeichenfolgen verwenden. Deshalb:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
In Bezug auf den Unterschied zwischen "==" und "is" sollte das Testen der Objektidentität mit "==" ausreichend sein. Da die Operation "ist" jedoch als Objektidentitätsoperation definiert ist, ist es wahrscheinlich korrekter, sie zu verwenden, als "==". Ich bin mir nicht sicher, ob es überhaupt einen Geschwindigkeitsunterschied gibt.
Wie auch immer, Sie können einen Blick darauf werfen:
0 == falsekehrt trueist , weil die Doppel-Gleichheitsoperator Art Zwang tut. Mit dem Triple-Equals-Operator wird jedoch 0 === falsezurückgegeben false, da 'number' und 'boolean' unterschiedliche Typen sind.
truein Bedingungen behandelt . In Rust and Go 0und false sind verschiedene Typen, die nicht für Gleichheit verglichen werden können.
Null ist ein spezieller Objekttyp wie:
>>>type(None)
<class 'NoneType'>
Sie können überprüfen, ob sich ein Objekt in der Klasse 'NoneType' befindet:
>>>variable = None
>>>variable is None
True
Weitere Informationen finden Sie unter Python Docs
Bei der Prüfung des Wahrheitswertes wird 'Keine' direkt als FALSCH getestet, sodass der einfachste Ausdruck ausreicht:
if not foo:
Truefür jeden falschen Wert zurückgegeben, nicht nur None.
egg is Noneüberegg == None: Letzteres kann überlastet werden und ist wahrscheinlich zu brechen , wenn sie mit keinem gültigen Objekt zu vergleichen (hängt davon ab , wie es umgesetzt wird , aber erwarten Sie nicht alle Vergleiche mit nehmen Keiner Rechnung, nicht wahr?) , währendisimmer gleich funktioniert.