Ich frage mich, warum eine Klasse __dict__
eine ist mappingproxy
, aber eine Instanz __dict__
ist nur eine Ebenedict
>>> class A:
... pass
>>> a = A()
>>> type(a.__dict__)
<class 'dict'>
>>> type(A.__dict__)
<class 'mappingproxy'>
Antworten:
Auf diese Weise kann der Interpreter sicherstellen, dass die Schlüssel für Attribute und Methoden auf Klassenebene nur Zeichenfolgen sein können.
An anderer Stelle ist Python eine "zustimmende Sprache für Erwachsene", was bedeutet, dass Diktate für Objekte vom Benutzer offengelegt und veränderbar sind. Wenn wir jedoch bei Attributen und Methoden auf Klassenebene für Klassen garantieren können, dass die Schlüssel Zeichenfolgen sind, können wir den allgemeinen Fallcode für die Suche nach Attributen und Methoden auf Klassenebene vereinfachen und beschleunigen. Insbesondere wird die Suchlogik __mro__ für Klassen neuen Stils vereinfacht und beschleunigt, indem angenommen wird, dass die Klassendiktatschlüssel Zeichenfolgen sind.
type.__setattr__
(was hoffentlich / wahrscheinlich ein ziemlich kleiner Satz ist), da Sie nicht schreiben können __dict__
; du musst verwenden super()
.
gc.get_referents(FooClass.__dict__)[0]['__eq__'] = eqmethod
, werden Instanzen von FooClass
möglicherweise nicht eqmethod
für ==
Vergleiche verwendet.
Ein Mapping-Proxy ist einfach ein Diktat ohne __setattr__
Methode.
Sie können diesen Code auschecken und darauf verweisen.
from types import MappingProxyType
d={'key': "value"}
m = MappingProxyType(d)
print(type(m)) # <class 'mappingproxy'>
m['key']='new' #TypeError: 'mappingproxy' object does not support item assignment
Zuordnungsproxy ist seit Python 3.3. Der folgende Code zeigt Diktattypen:
class C:pass
ci=C()
print(type(C.__dict__)) #<class 'mappingproxy'>
print(type(ci.__dict__)) #<class 'dict'>
Da Python 3.3 mappingproxy
wurde Typ umbenannt aus dictproxy
. Es gab eine interessante Diskussion zu diesem Thema.
Es ist ein bisschen schwierig, die Dokumentation für diesen Typ zu finden, aber die Dokumentation für die vars- Methode beschreibt dies perfekt (obwohl sie eine Weile nicht dokumentiert war ):
Objekte wie Module und Instanzen verfügen über ein aktualisierbares
__dict__
Attribut. Bei anderen Objekten können jedoch Schreibbeschränkungen für ihre__dict__
Attribute gelten (z. B. verwenden Klassen einen types.MappingProxyType, um direkte Wörterbuchaktualisierungen zu verhindern).
Wenn Sie ein neues Klassenattribut zuweisen müssen, können Sie es verwenden setattr
. Beachten Sie, dass mappingproxy
JSON nicht serialisierbar ist. Überprüfen Sie das Problem, um zu verstehen, warum.
Auch die Geschichte dieses Typs ist sehr interessant:
Python 2.7: type(A.__dict__)
gibt <type 'dict'>
as zurück type(dict())
und es ist möglich, neue Attribute zuzuweisen __dict__
, z
A.__dict__['foo'] = 'bar'
.
Python 3.0 - 3.2: type(A.__dict__)
kehrt zurück <class 'dict_proxy'>
, der Unterschied ist jetzt etwas deutlicher. Der Versuch, ein neues Attribut zuzuweisen, ergibt TypeError
. Es wurde versucht , dictproxy
einen öffentlich eingebauten Typ hinzuzufügen.
<class 'mappingproxy'>
den oben beschriebenen Typ hinzu .
mappingproxy
machtclass.__dict__
schreibgeschützt, so dass nurclass.__setattr__
noch ein Weg zum Festlegen von Klassenattributen bleibt, und es ist diese Methode, die die Einschränkung erzwingt .