Leicht verdaulich (mit Beispielen) Erläuterung für __get__ & __set__ & __call__
im Unterricht, was ist Owner, Instance
?
Einige Punkte zum Nachdenken, bevor Sie eintauchen:
__get__ __set__
werden Deskriptoren der Klasse genannt, um ihre internen Attribute zu bearbeiten/speichern, nämlich: __name__
(Name der Klasse/Besitzerklasse), Variablen - __dict__
usw. Ich werde später erklären, was ein Eigentümer ist
- Deskriptoren werden in Design-Patterns häufiger verwendet, z. B. mit Dekoratoren (um Dinge zu abstrahieren). Man kann davon ausgehen, dass sie häufiger in der Software-Architektur verwendet werden, um Dinge weniger redundant und besser lesbar zu machen (scheint ironisch). Auf diese Weise werden die Prinzipien von SOLID und DRY eingehalten.
- Wenn Sie keine Software entwickeln, die den SOLID- und DRY-Prinzipien entsprechen soll, brauchen Sie sie wahrscheinlich nicht, aber es ist immer sinnvoll, sie zu verstehen.
1. Berücksichtigen Sie diesen Code:
class Method:
def __init__(self, name):
self.name = name
def __call__(self, instance, arg1, arg2):
print(f"{self.name}: {instance} called with {arg1} and {arg2}")
class MyClass:
method = Method("Internal call")
instance = MyClass()
instance.method("first", "second")
# Prints:TypeError: __call__() missing 1 required positional argument: 'arg2'
Also, wenn instance.method("first", "second")
genannt wird, __call__
Methode wird von der Klasse Method aufgerufen (call method macht ein Klassenobjekt einfach aufrufbar wie eine Funktion - wann immer eine Klasseninstanz aufgerufen wird __call__
wird instanziiert), und die folgenden Argumente werden zugewiesen: instance: "first", arg1: "second"
und das letzte arg2 ausgelassen wird, wird ein Fehler ausgegeben: TypeError: __call__() missing 1 required positional argument: 'arg2'
2. Wie kann man das Problem lösen?
-
から __call__
nimmt instance
als erstes Argument (Instanz, arg1, arg2), aber instance
von was?
-
Instance
ist die Instanz der Hauptklasse (MyClass), die die Deskriptorklasse (Method) aufruft. So, instance = MyClass()
es el instance
und wer ist also der owner
? die Klasse, die die Diskriptorklasse enthält - MyClass
Es gibt jedoch keine Methode in unserer Deskriptorklasse (Method)
sie als eine instance
. Das ist also der Punkt, an dem wir brauchen __get__
Methode. Betrachten Sie noch einmal den folgenden Code:
from types import MethodType
class Method:
def init(self, name):
self.name = name
def call(self, instance, arg1, arg2):
print(f"{self.name}: {instance} called with {arg1} and {arg2}")
def set(self, instance, value):
self.value = value
instance.dict["method"] = value
def get(self, instance, owner):
if instance is None:
return self
print (instance, owner)
return MethodType(self, instance)
class MyClass:
method = Method("Internal call")
instance = MyClass()
instance.method("first", "second")
Prints: Internal call: <main.MyClass object at 0x7fb7dd989690> called with first and second
vergessen einstellen. für den Moment laut den Unterlagen:
__get__
"Wird aufgerufen, um das Attribut der Eigentümerklasse (Klassenattribut-Zugriff) oder einer Instanz dieser Klasse (Instanzattribut-Zugriff) zu erhalten."
wenn Sie es tun: instance.method.__get__(instance)
Prints:<__main__.MyClass object at 0x7fb7dd9eab90> <class '__main__.MyClass'>
dies bedeutet Instanz: Objekt von MyClass
das ist instance
y Owner
es MyClass
selbst
3. __set__
Erläuterung:
__set__
wird verwendet, um einen Wert in der Klasse __dict__
Objekts (z. B. über eine Befehlszeile). Befehl zum Setzen des internen Werts für einstellen. ist: instance.descriptor = 'value'
# wo der Deskriptor ist method
in diesem Fall
-
( instance.__dict__["method"] = value
im Code aktualisieren Sie einfach die __dict__
Objekt des Deskriptors)
-
So auch hier: instance.method = 'value'
jetzt zu prüfen, ob die value = 'value'
wird in der Datei __set__
Methode können wir auf __dict__
Objekt des Deskriptors method
. Machen: instance.method.__dict__
Drucke: {'_name': 'Internal call', 'value': 'value'}
-
Oder Sie können die __dict__
Wert mit vars(instance.method)
Drucke: {'name': 'Internal call', 'value': 'value'}
Ich hoffe, die Dinge sind jetzt klar:)