Wie beziehe ich mich auf die Nullobjekt in Python?
Null-Objekt in Python
Eidechse
Ben James
In Python ist das „Null“-Objekt das Singleton None
.
Um zu überprüfen, ob etwas ist None
verwenden Sie die is
Identitätsoperator:
if foo is None:
...
-
Und der Grund für die Wahl
egg is None
Überegg == None
: Letzteres kann überladen werden und bricht wahrscheinlich zusammen, wenn ein gültiges Objekt mit None verglichen wird (hängt davon ab, wie es implementiert ist, aber Sie erwarten nicht, dass jeder Vergleiche mit None berücksichtigt, oder?), whileis
funktioniert immer gleich.– Benutzer395760
20. Juli 2010 um 12:25 Uhr
-
Warum haben die Python-Designer nicht einfach “null” gewählt? Man muss einfach anders sein, nicht wahr? 😉
– Vidar
26. März 2013 um 9:44 Uhr
-
@Vidar ‘None’ ist kein Fehlen eines Objekts (wie ‘null’ eine Nullreferenz ist), es ist ein tatsächliches Objekt. Sie erhalten niemals ein ‘None’-Objekt, das für ein Objekt übergeben wird, das einen anderen Typ als ‘NoneType’ hat. Es ist auch kein Sprachkonzept. Es ist nicht in die Sprache Python integriert, sondern Teil der Standardbibliothek von Python. Keine !== (ähm) Null
– Rushyo
12. Juni 2013 um 12:17 Uhr
-
@ naught101 Es würde keinen Zweck erfüllen; da es kein Konzept von Zeigern gibt. Wenn Sie die ctypes-Bibliothek verwenden, wird None als Synonym für die Adresse Null verwendet, aber es gibt immer noch kein Sprachkonzept einer ‘Nullreferenz’. In Python haben Sie immer auf eine Art Objekt verwiesen, selbst wenn dieses Objekt None ist. Ich vermute, dass dies die Sprache stark vereinfacht.
– Rushyo
2. September 2014 um 13:26 Uhr
-
großartige Präsentation, die den “Milliarden-Dollar-Fehler” erklärt, der der Null-Ref ist: infoq.com/presentations/…. Andere Optionen anstelle von null sind Optionen oder vielleicht (benutzerdefinierte) Typen.
– Michael Trouv
8. April 2015 um 23:56 Uhr
Michael Ekoka
None
Python ist null?
Da ist kein null
in Python; stattdessen gibt es None
. Wie bereits erwähnt, der genaueste Weg, um zu testen, ob etwas gegeben wurde None
als Wert ist die zu verwenden is
Identitätsoperator, der testet, ob zwei Variablen auf dasselbe Objekt verweisen.
>>> foo is None
True
>>> foo = 'bar'
>>> foo is None
False
Die Grundlagen
Es gibt und kann nur einen geben None
None
ist die einzige Instanz der Klasse NoneType
und alle weiteren Versuche, diese Klasse zu instanziieren, werden dasselbe Objekt zurückgeben, was macht None
ein Einzelgänger. Neulinge in Python sehen oft Fehlermeldungen, die erwähnen NoneType
und frage mich, was es ist. Es ist meine persönliche Meinung, dass man diese Meldungen einfach nur erwähnen könnte None
namentlich, weil, wie wir gleich sehen werden, None
lässt wenig Raum für Mehrdeutigkeiten. Also, wenn Sie einige sehen TypeError
Nachricht, die das erwähnt NoneType
kann dies nicht oder kann das nicht, wisse einfach, dass es einfach das eine ist None
das wurde auf eine Weise verwendet, die es nicht kann.
Ebenfalls, None
ist eine eingebaute Konstante. Sobald Sie Python starten, steht es überall zur Verfügung, ob in Modul, Klasse oder Funktion. NoneType
im Gegensatz dazu nicht, Sie müssten zuerst durch Abfragen einen Verweis darauf erhalten None
für seine Klasse.
>>> NoneType
NameError: name 'NoneType' is not defined
>>> type(None)
NoneType
Du kannst nachschauen None
mit der Identitätsfunktion von Python id()
. Es gibt die eindeutige Nummer zurück, die einem Objekt zugewiesen ist, jedes Objekt hat eine. Wenn die ID zweier Variablen gleich ist, dann zeigen 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 werden
In viel älteren Python-Versionen (vor 2.4) war eine Neuzuweisung möglich None
, aber nicht mehr. Nicht einmal als Klassenattribut oder innerhalb 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 None
Referenzen sind die gleichen. Es gibt keinen “Brauch” None
.
Zum Testen None
benutze die is
Operator
Beim Schreiben von Code könnten Sie versucht sein, dies zu testen Nichtigkeit so was:
if value==None:
pass
Oder um so auf Unwahrheit zu testen
if not value:
pass
Sie müssen die Auswirkungen verstehen und wissen, warum es oft eine gute Idee ist, explizit zu sein.
Fall 1: Testen, ob ein Wert vorhanden ist None
Warum machen
value is None
statt
value==None
?
Das erste ist äquivalent zu:
id(value)==id(None)
Während der Ausdruck value==None
wird tatsächlich so angewendet
value.__eq__(None)
Wenn der Wert wirklich ist None
dann bekommst du was du erwartet hast.
>>> nothing = function_that_does_nothing()
>>> nothing.__eq__(None)
True
In den meisten Fällen wird das Ergebnis das gleiche sein, aber die __eq__()
-Methode öffnet eine Tür, die jegliche Genauigkeitsgarantie aufhebt, 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 aus None
und es funktioniert
>>> empty = Empty()
>>> empty==None
True
Aber dann funktioniert es auch auf dem leeren String
>>> empty==''
True
Und doch
>>> ''==None
False
>>> empty is None
False
Fall 2: Verwenden None
als Boolean
Die folgenden zwei Tests
if value:
# Do something
if not value:
# Do something
werden tatsächlich als bewertet
if bool(value):
# Do something
if not bool(value):
# Do something
None
ist ein “Falsey”, was bedeutet, dass es zurückgegeben wird, wenn es in einen booleschen Wert umgewandelt wird False
und falls angewendet die not
Betreiber wird es zurückkehren True
. Beachten Sie jedoch, dass es sich nicht um eine einzigartige Eigenschaft handelt None
. Zusätzlich zu False
selbst wird die Eigenschaft von leeren Listen, Tupeln, Mengen, Wörtern, Zeichenfolgen sowie 0 und allen Objekten von Klassen geteilt, die die implementieren __bool__()
magische Methode zur Rückkehr 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
Wenn Sie also auf folgende Weise auf Variablen testen, achten Sie besonders darauf, was Sie in den Test einbeziehen oder daraus ausschließen:
def some_function(value=None):
if not value:
value = init_value()
Wollten Sie oben anrufen init_value()
wenn der Wert speziell auf eingestellt ist None
oder meintest du das auf einen Wert gesetzt 0
, oder der leere String, oder eine leere Liste soll auch die Initialisierung auslösen? Wie gesagt, sei achtsam. Wie so oft in Python explizit ist besser als implizit.
None
in der Praxis
None
als Signalwert verwendet
None
hat in Python einen Sonderstatus. Dies 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 Setzen eines Standardwerts).
Sie können zuweisen None
zu den Schlüsselwortargumenten einer Funktion und dann explizit darauf 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, zum Attribut eines Objekts zu gelangen, 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 ein Wörterbuch get()
Methode zurück None
beim Versuch, auf einen nicht vorhandenen Schlüssel zuzugreifen:
>>> some_dict = {}
>>> value = some_dict.get('foo')
>>> value is None
True
Wenn Sie versuchen würden, darauf zuzugreifen, indem Sie die tiefgestellte Schreibweise a verwenden KeyError
erhoben würden
>>> value = some_dict['foo']
KeyError: 'foo'
Ebenso, wenn Sie versuchen, ein nicht vorhandenes Element zu platzieren
>>> value = some_dict.pop('foo')
KeyError: 'foo'
die Sie mit einem normalerweise eingestellten Standardwert unterdrücken können None
value = some_dict.pop('foo', None)
if value is None:
# Booom!
None
wird sowohl als Flag als auch als gültiger Wert verwendet
Die oben beschriebenen Verwendungen von None
gelten, wenn es nicht als gültiger Wert angesehen wird, sondern eher als Signal, etwas Besonderes zu tun. Es gibt jedoch Situationen, in denen es manchmal wichtig ist zu wissen, wo None
stammt, weil es, obwohl es als Signal verwendet wird, auch Teil der Daten sein könnte.
Wenn Sie ein Objekt nach seinem Attribut mit abfragen getattr(some_obj, 'attribute_name', None)
zurückkommen None
sagt Ihnen nicht, ob das Attribut, auf das Sie zugreifen wollten, festgelegt wurde None
oder wenn es überhaupt vom Objekt fehlte. Die gleiche Situation beim Zugriff auf einen Schlüssel aus einem Wörterbuch, z some_dict.get('some_key')
du weißt nicht ob some_dict['some_key']
fehlt oder nur darauf eingestellt ist None
. Wenn Sie diese Informationen benötigen, besteht die übliche Vorgehensweise darin, direkt zu versuchen, auf das Attribut oder den Schlüssel innerhalb von a zuzugreifen try/except
konstruieren:
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 handling 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 dict:
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 beiden obigen Beispiele zeigen, wie Objekt- und Wörterbuchfälle behandelt werden. Was ist mit Funktionen? Das Gleiche, aber wir verwenden zu diesem Zweck das Schlüsselwortargument doppelte 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
nur als gültiger Wert verwendet
Wenn Sie feststellen, dass Ihr Code mit dem oben Gesagten übersät ist try/except
Muster einfach zu unterscheiden None
Fahnen u None
Daten, dann 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 und zum Steuern und Testen spezieller Bedingungen (z. B. Grenzen, Status usw.) verwendet wird. Einen solchen Wert nennt man a Wächter und es kann so verwendet werden None
wird als Signal verwendet. Es ist trivial, einen Sentinel in Python zu erstellen.
undefined = object()
Das undefined
Das obige Objekt ist einzigartig und macht nicht viel von allem, was für ein Programm von Interesse sein könnte, es ist daher ein ausgezeichneter Ersatz für None
als Fahne. 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 überschreiben undefined
oben jederzeit und überall im Modul, wo es definiert ist, seien Sie also vorsichtig, wie Sie sie verfügbar machen und verwenden. Als nächstes wird die Instanz zurückgegeben von object()
ist kein Single. Wenn Sie diesen Anruf 10 Mal machen, erhalten Sie 10 verschiedene Objekte. Schließlich ist die Verwendung eines Sentinels höchst eigenwillig. Ein Sentinel ist spezifisch für die Bibliothek, in der er verwendet wird, und daher sollte sein Geltungsbereich im Allgemeinen auf die Interna der Bibliothek beschränkt sein. Es darf nicht “auslaufen”. Externer Code sollte nur dann darauf aufmerksam werden, wenn er dazu dient, die API der Bibliothek zu erweitern oder zu ergänzen.
-
Was ist mit: None == thing ?
– hkBst
1. November 2018 um 9:56 Uhr
-
@hkBst Ich vermute, Ihre Frage bezieht sich darauf, wie Python die Gleichheit auswertet. Schauen Sie sich dies an: http://stackoverflow.com/questions/3588776/…
– Michael Ekoka
1. November 2018 um 17:02 Uhr
-
Ah, also IIUC, das normalerweise immer noch Ding anruft.__eq__? In diesem Fall ziehe ich meinen Vorschlag zurück.
– hkBst
2. November 2018 um 9:56 Uhr
-
@MichaelEkoka kannst du die Quelle für diese beeindruckenden und nützlichen Informationen teilen.
– Anidhya Bhatnagar
25. Dezember 2018 um 6:46 Uhr
-
Standardverfahren. Sie können einige Hinweise darauf finden, wenn Sie durch die gehen Python-Tutorialaber das Lesen des Quellcodes beliebter Projekte ist mein wichtigster Rat, um schnell einzutauchen idiomatische Python.
– Michael Ekoka
14. April 2019 um 5:53 Uhr
Es heißt nicht null wie in anderen Sprachen, sondern None
. Es gibt immer nur eine Instanz dieses Objekts, mit der Sie auf Äquivalenz prüfen können x is None
(Identitätsvergleich) statt x == None
falls Sie es wollen.
-
Ich werde einen Weg finden, Python durch erneutes Instanziieren zu brechen
None
. Dann all diese schlauen Leute, die sich verglichen habenNoneType
wird triumphieren!– Zenexer
27. August 2013 um 3:40 Uhr
In Python können Sie das verwenden, um das Fehlen eines Werts darzustellen Keiner Wert (Typen.NoneTyp.None) für Objekte und “” (oder len() == 0) für Streicher. Deswegen:
if yourObject is None: # if yourObject == None:
...
if yourString == "": # if yourString.len() == 0:
...
In Bezug auf den Unterschied zwischen „==“ und „ist“ sollte das Testen der Objektidentität mit „==“ ausreichend sein. Da jedoch die Operation „is“ als Objektidentitätsoperation definiert ist, ist es wahrscheinlich korrekter, sie anstelle von „==“ zu verwenden. Ich bin mir nicht sicher, ob es überhaupt einen Geschwindigkeitsunterschied gibt.
Auf jeden Fall kann man sich anschauen:
- Python Eingebaute Konstanten doc-Seite.
- Python Wahrheitswertprüfung doc-Seite.
Es ergeben sich nur die obigen Antworten True
zum None
aber es gibt so etwas wie float('nan')
. Sie könnten Pandas verwenden isnull
:
>>> import pandas as pd
>>> pd.isnull(None)
True
>>> pd.isnull(float('nan'))
True
>>> pd.isnull('abc')
False
>>>
Oder ohne pandas
:
>>> a = float('nan')
>>> (a != a) or (a == None)
True
>>> a = None
>>> (a != a) or (a == None)
True
>>>
Der Grund, warum dies funktioniert, ist, weil float('nan') != float('nan')
:
>>> float('nan') == float('nan')
False
>>> float('nan') != float('nan')
True
>>>
s_mj
Verwenden f
Zeichenfolge, um dies zu lösen.
year=None
year_val="null" if year is None else str(year)
print(f'{year_val}')
null
Einfache Funktion, um “leere” Elemente in Python anzugehen:
Code:
def is_empty(element) -> bool:
"""
Function to check if input `element` is empty.
Other than some special exclusions and inclusions,
this function returns boolean result of Falsy check.
"""
if (isinstance(element, int) or isinstance(element, float)) and element == 0:
# Exclude 0 and 0.0 from the Falsy set.
return False
elif isinstance(element, str) and len(element.strip()) == 0:
# Include string with one or more empty space(s) into Falsy set.
return True
elif isinstance(element, bool):
# Exclude False from the Falsy set.
return False
else:
# Falsy check.
return False if element else True
Prüfen:
print("Is empty?\n")
print('"" -> ', is_empty(""))
print('" " -> ', is_empty(" "))
print('"A" -> ', is_empty("A"))
print('"a" -> ', is_empty("a"))
print('"0" -> ', is_empty("0"))
print("0 -> ", is_empty(0))
print("0.0 -> ", is_empty(0.0))
print("[] -> ", is_empty([]))
print("{} -> ", is_empty({}))
print("() -> ", is_empty(()))
print("[1, 2] -> ", is_empty([1, 2]))
print("(3, 5) -> ", is_empty((3, 5)))
print('{"a": 1} -> ', is_empty({"a": 1}))
print("None -> ", is_empty(None))
print("True -> ", is_empty(True))
print("False -> ", is_empty(False))
print("NaN -> ", is_empty(float("nan")))
print("range(0) -> ", is_empty(range(0)))
Ausgabe:
Is empty?
"" -> True
" " -> True
"A" -> False
"a" -> False
"0" -> False
0 -> False
0.0 -> False
[] -> True
{} -> True
() -> True
[1, 2] -> False
(3, 5) -> False
{"a": 1} -> False
None -> True
True -> False
False -> False
NaN -> False
range(0) -> True