Heim >Backend-Entwicklung >Python-Tutorial >Lernen der magischen Python-Funktion __missing__
Dieser Artikel bringt Ihnen relevantes Wissen über Python, das hauptsächlich Probleme im Zusammenhang mit der Funktion „__missing__()“ vorstellt. Ich hoffe, dass sie für alle hilfreich ist.
Empfohlenes Lernen: Python-Lern-Tutorial
Beim Abrufen des Werts aus einem gewöhnlichen Wörterbuch existiert der Schlüssel möglicherweise nicht:
dd = {'name':'PythonCat'} dd.get('age') # 结果:None dd.get('age', 18) # 结果:18 dd['age'] # 报错 KeyError dd.__getitem__('age') # 等同于 dd['age']
Für den get ()-Methode verfügt über einen Rückgabewert und der zweite Parameter kann als Rückgabeinhalt übergeben werden, wenn der Schlüssel nicht vorhanden ist, sodass dies akzeptabel ist. Die anderen beiden Schreibmethoden melden jedoch Fehler.
Um das Problem der beiden letztgenannten Schreibmethoden zu lösen, können Sie die magische Methode __missing__() verwenden.
Angenommen, wir haben eine Anfrage wie diese: Nehmen Sie den Wert, der einem Schlüssel entspricht, aus dem Wörterbuch, geben Sie den Wert zurück, wenn ein Wert vorhanden ist, fügen Sie den Schlüssel ein, wenn kein Wert vorhanden ist, und geben Sie ihm einen Standardwert (z. B eine leere Liste).
Wenn Sie natives Diktat verwenden, ist die Implementierung nicht einfach. Python bietet jedoch eine sehr einfach zu verwendende Erweiterungsklasse collections.defaultdict
: collections.defaultdict
:
如图所示,当取不存在的 key 时,没有再报 KeyError,而是默认存入到字典中。
为什么 defaultdict 可以做到这一点呢?
原因是 defaultdict 在继承了内置类型 dict 之后,还定义了一个 __missing__() 方法,当 __getitem__取不存在的值时,它就会调用入参中传入的工厂函数(上例是调用 list(),创建空列表)。
作为最典型的示例,defaultdict 在文档注释中写到:
简而言之,__missing__()的主要作用就是由__getitem__在缺失 key 时调用,从而避免出现 KeyError。
另外一个典型的使用例子是collections.Counter
,它也是 dict 的子类,在取未被统计的 key 时,返回计数 0:
由上可知,__missing__()在__getitem__()取不到值时会被调用,但是,我不经意间还发现了一个细节:__getitem__()在取不到值时,并不一定会调用__missing__()。
这是因为它并非内置类型的必要属性,并没有在字典基类中被预先定义。
如果你直接从 dict 类型中取该属性值,会报属性不存在:AttributeError: type object 'object' has no attribute '__missing__'
Warum kann defaultdict das tun?
Der Grund dafür ist, dass defaultdict auch eine __missing__()-Methode definiert, nachdem der integrierte Typ dict geerbt wurde. Wenn __getitem__ einen nicht vorhandenen Wert annimmt, ruft es die im Eingabeparameter übergebene Factory-Funktion auf (das obige Beispiel ist Call list). (), wodurch eine leere Liste erstellt wird).
Als typischstes Beispiel schreibt defaultdict in den Dokumentationskommentaren:
Kurz gesagt besteht die Hauptfunktion von __missing__() darin, von __getitem__ aufgerufen zu werden, wenn der Schlüssel fehlt, wodurch KeyError vermieden wird.
Ein weiteres typisches Anwendungsbeispiel istcollections.Counter
, das ebenfalls eine Unterklasse von dict ist. Wenn ein nicht gezählter Schlüssel verwendet wird, wird eine Anzahl von 0 zurückgegeben:
2.
Von As can Wie oben zu sehen ist, wird __missing__() aufgerufen, wenn __getitem__() den Wert nicht erhalten kann. Ich habe jedoch versehentlich ein Detail entdeckt:__getitem__() ruft nicht unbedingt __missing__( auf, wenn es den Wert nicht erhalten kann. ).
Das liegt daran, dass es kein notwendiges Attribut des integrierten Typs ist und in der Wörterbuch-Basisklasse nicht vordefiniert ist.Wenn Sie den Attributwert direkt aus dem Diktattyp übernehmen, wird gemeldet, dass das Attribut nicht vorhanden ist: AttributeError: type object 'object' has no attribute '__missing__'
.
Und das ist interessant: Magische Methoden, die nur für Unterklassen integrierter Typen existieren. Wenn man sich die gesamte Python-Welt ansieht, ist es wahrscheinlich schwierig, ein zweites Beispiel zu finden.
Plötzlich hatte ich eine Assoziation: Dieses schwer fassbare __missing__() ist wie ein Zauberer, der gut darin ist, „eine lebende Person zu verwandeln“. Beim Öffnen befindet er sich nicht im Inneren (d. h. ein eingebauter Typ), und wenn die Requisiten geändert werden, erscheint er wieder intakt (d. h. eine Unterklasse von dict).
__missing__() erfordert zusätzlich zur „Magie“ selbst auch eine mächtige „Magie“, um angetrieben zu werden.
Im letzten Artikel habe ich festgestellt, dass die nativen magischen Methoden unabhängig voneinander sind. Sie haben möglicherweise dieselbe Kernlogik in der C-Sprachschnittstelle, aber in der Python-Sprachschnittstelle gibt es keine Aufrufbeziehung:
Magic Diese Art der „kontaktlosen“ Leistung von Methoden verstößt gegen das allgemeine Prinzip der Code-Wiederverwendung und ist auch der Grund, warum Unterklassen integrierter Typen einige seltsame Verhaltensweisen aufweisen.
Offizielles Python stellt lieber neue UserString-, UserList- und UserDict-Unterklassen bereit, als magische Methoden wiederzuverwenden. Die einzig vernünftige Erklärung scheint zu sein, dass die Kosten für den gegenseitigen Aufruf magischer Methoden zu hoch sind.
Für den Sonderfall __missing__() muss Python jedoch Kompromisse eingehen und diesen Preis zahlen!
__missing__() ist ein „Bürger zweiter Klasse“ magischer Methoden. Es hat keinen unabhängigen Aufrufeintrag und kann nur passiv von __getitem__() aufgerufen werden, das heißt, __missing__() hängt von __getitem__() ab.
Im Gegensatz zu diesen „Erstklassigen Bürgern“ wie __init__(), __enter__(), __len__(), __eq__() usw. werden sie entweder an einem bestimmten Knoten im Objektlebenszyklus oder bei der Ausführung ausgelöst Prozess. Entweder durch eine integrierte Funktion oder einen Operator ausgelöst, handelt es sich um relativ unabhängige Ereignisse und ohne Abhängigkeiten.
__missing__() hängt von __getitem__() ab, um den Methodenaufruf zu erreichen, und __getitem__() hängt auch von __missing__() ab, um die vollständige Funktionalität zu erreichen.
Um dies zu erreichen, öffnet __getitem__() eine Hintertür im Interpretercode und kehrt von der C-Sprachschnittstelle zur Python-Schnittstelle zurück, um die spezifische Methode namens „__missing__“ aufzurufen. Und das ist die wahre „Magie“. Bisher scheint __missing__() die einzige magische Methode zu sein, die eine solche Behandlung genießt! 4. ZusammenfassungPythons Wörterbuch bietet zwei integrierte Methoden zum Abrufen von Werten, nämlich __getitem__() und get(). Wenn der Wert nicht vorhanden ist, sind ihre Verarbeitungsstrategien unterschiedlich:Ersteres meldet einen Fehler KeyError
, der None zurückgibt. KeyError
,而后者会返回 None。
为什么 Python 要提供两个不同的方法呢?或者应该问,为什么 Python 要令这两个方法做出不一样的处理呢?
这可能有一个很复杂(也可能是很简单)的解释,本文暂不深究了。
不过有一点是可以确定的:即原生 dict 类型简单粗暴地抛KeyError
Aber eines ist sicher: Der native Diktattyp löst einfach und grob KeyError
aus.
Es ist der einzige Sonderfall, der die Barrieren zwischen magischen Methoden durchbricht und den Aufruf durch andere magische Methoden unterstützt!
Um die Unabhängigkeit magischer Methoden zu wahren, hat sich Python große Mühe gegeben, abgeleitete Klassen wie UserString, UserList und UserDict einzuführen, entschied sich jedoch für __missing__() für einen Kompromiss. 🎜🎜Empfohlenes Lernen: 🎜Python-Tutorial🎜🎜Das obige ist der detaillierte Inhalt vonLernen der magischen Python-Funktion __missing__. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!