Heim >Backend-Entwicklung >Python-Tutorial >Lernen der magischen Python-Funktion __missing__

Lernen der magischen Python-Funktion __missing__

WBOY
WBOYOriginal
2022-03-11 17:23:222435Durchsuche

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.

Lernen der magischen Python-Funktion __missing__

Empfohlenes Lernen: Python-Lern-Tutorial

1. Das etwas wertvolle __missing__()

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']

Lernen der magischen Python-Funktion __missing__

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

Lernen der magischen Python-Funktion __missing__

如图所示,当取不存在的 key 时,没有再报 KeyError,而是默认存入到字典中。

为什么 defaultdict 可以做到这一点呢?

原因是 defaultdict 在继承了内置类型 dict 之后,还定义了一个 __missing__() 方法,当 __getitem__取不存在的值时,它就会调用入参中传入的工厂函数(上例是调用 list(),创建空列表)。

作为最典型的示例,defaultdict 在文档注释中写到:

Lernen der magischen Python-Funktion __missing__

简而言之,__missing__()的主要作用就是由__getitem__在缺失 key 时调用,从而避免出现 KeyError。

另外一个典型的使用例子是collections.Counter,它也是 dict 的子类,在取未被统计的 key 时,返回计数 0:

Lernen der magischen Python-Funktion __missing__

2、神出鬼没的__missing__()

由上可知,__missing__()在__getitem__()取不到值时会被调用,但是,我不经意间还发现了一个细节:__getitem__()在取不到值时,并不一定会调用__missing__()。

这是因为它并非内置类型的必要属性,并没有在字典基类中被预先定义。

如果你直接从 dict 类型中取该属性值,会报属性不存在:AttributeError: type object 'object' has no attribute '__missing__'

Lernen der magischen Python-Funktion __missing__

Wie in der Abbildung gezeigt, wenn. f Ätzen eines nicht existierenden Schlüssels Zeit, kein KeyError mehr melden, sondern standardmäßig im Wörterbuch speichern.

Lernen der magischen Python-Funktion __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:

Lernen der magischen Python-Funktion __missing__

Kurz gesagt besteht die Hauptfunktion von Lernen der magischen Python-Funktion __missing____missing__() darin, von __getitem__ aufgerufen zu werden, wenn der Schlüssel fehlt, wodurch KeyError vermieden wird.

Ein weiteres typisches Anwendungsbeispiel ist collections.Counter, das ebenfalls eine Unterklasse von dict ist. Wenn ein nicht gezählter Schlüssel verwendet wird, wird eine Anzahl von 0 zurückgegeben:

Lernen der magischen Python-Funktion __missing__

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.

Lernen der magischen Python-Funktion __missing__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__'.

🎜Verwenden Sie dir(), um zu überprüfen und festzustellen, ob das Attribut nicht existiert: 🎜🎜🎜🎜🎜Wenn Sie anhand der übergeordneten Klasse von dict prüfen, bei der es sich um ein Objekt handelt, erhalten Sie ebenfalls das gleiche Ergebnis. 🎜🎜Was ist los? Warum gibt es weder im Diktat noch im Objekt das Attribut __missing__? 🎜🎜Eine Überprüfung der neuesten offiziellen Dokumentation zeigt jedoch, dass das Objekt eindeutig dieses Attribut enthält: 🎜🎜🎜🎜🎜Quelle: https://docs.python.org/3/reference/datamodel.html?highlight=__missing__#object.__missing__🎜 🎜 Mit anderen Worten: Theoretisch wird __missing__ in der Objektklasse vordefiniert sein, und die Dokumentation beweist dies, aber tatsächlich ist es nicht definiert! Es besteht eine Diskrepanz zwischen Dokument und Realität! 🎜🎜Wenn also eine Unterklasse von dict (z. B. defaultdict und Counter) __missing__ definiert, gehört diese magische Methode tatsächlich nur zu dieser Unterklasse, das heißt: 🎜Es handelt sich um eine magische Methode, die in der Unterklasse geboren wurde! 🎜🎜🎜Dementsprechend habe ich eine unausgereifte Vermutung: __getitem__() ermittelt, ob das aktuelle Objekt eine Unterklasse von dict ist und ob es __missing__() hat, und ruft es dann auf (wenn die übergeordnete Klasse auch diese Methode hat). es wird nicht zuerst ein Urteil fällen, sondern es direkt aufrufen). 🎜🎜Ich habe diese Vermutung in der Kommunikationsgruppe erwähnt und einige Schüler haben die Bestätigung schnell im CPython-Quellcode gefunden: 🎜🎜🎜🎜

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).

3. Die Magie des verzauberten __missing__()

__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:

Lernen der magischen Python-Funktion __missing__

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.

Lernen der magischen Python-Funktion __missing__

Und das ist die wahre „Magie“. Bisher scheint __missing__() die einzige magische Methode zu sein, die eine solche Behandlung genießt!

4. Zusammenfassung

Pythons 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

Warum bietet Python zwei verschiedene Methoden? Oder Sie sollten sich fragen: Warum geht Python mit diesen beiden Methoden unterschiedlich um?

Dies könnte eine sehr komplizierte (oder sehr einfache) Erklärung haben, auf die ich in diesem Artikel nicht näher eingehen werde.

Aber eines ist sicher: Der native Diktattyp löst einfach und grob KeyError aus.

Um dem Wörterbuchtyp eine leistungsfähigere Leistung zu verleihen (oder __getitem__() sich wie get() verhalten zu lassen), ermöglicht Python, dass Unterklassen des Wörterbuchs __missing__() für __getitem__() zum Suchen und Aufrufen definieren.

Dieser Artikel erläutert die Implementierungsprinzipien von __missing__() und zeigt, dass es sich nicht um eine unauffällige Existenz handelt, im Gegenteil:

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn