Immer wenn wir eine neue Klasse definieren, führt die Metaklasse Yazheng-Code aus, um sicherzustellen, dass die neue Klasse den angegebenen Spezifikationen entspricht.
Nachdem das Python-System die Klassenanweisung der Unterklasse verarbeitet hat, ruft es die Methode __new__
der Metaklasse auf. Die Metaklasse kann den Namen, die übergeordnete Klasse und die Attribute der Unterklasse und der Enkelklasse über die Methode __new__
abrufen.
Dadurch entfällt für uns die Notwendigkeit, den Verifizierungscode in die __init__
-Methode dieser Klasse einzufügen und mit der Verifizierung zu warten, bis das Objekt erstellt ist.
Im folgenden Beispiel wird eine Unterklasse mit weniger als 3 Kanten definiert. Sobald die Klassenanweisung endet, lehnt der Metaklassen-Verifizierungscode die Klasse ab.
class ValidatePolygon(type): def __new__(meta, name, bases, class_dict): # Don't validate the abstract Polygon class if bases != (object,): if class_dict['sides'] < 3: raise ValueError('Polygons need 3+ sides') return type.__new__(meta, name, bases, class_dict) class Polygon(object, metaclass=ValidatePolygon): sides = None # Specified by subclasses @classmethod def interior_angles(cls): return (cls.sides - 2) * 180 class Triangle(Polygon): sides = 3 print(Triangle.interior_angles())
Jedes Mal, wenn Sie eine Unterklasse von einer Basisklasse erben, kann die Metaklasse der Basisklasse den Registrierungscode automatisch ausführen.
Dies ist nützlich, wenn eine „Reverse-Lookup“ erforderlich ist, um eine Zuordnung zwischen einem einfachen Bezeichner und der entsprechenden Klasse herzustellen.
Was noch verwendet wird, ist, dass nach der Ausführung der Klassenanweisung automatisch die Methode __new__
der Metaklasse aufgerufen wird.
import json registry = {} def register_class(target_class): registry[target_class.__name__] = target_class def deserialize(data): params = json.loads(data) name = params['class'] target_class = registry[name] return target_class(*params['args']) class Meta(type): def __new__(meta, name, bases, class_dict): cls = type.__new__(meta, name, bases, class_dict) register_class(cls) return cls class Serializable(object): def __init__(self, *args): self.args = args def serialize(self): return json.dumps({ 'class': self.__class__.__name__, 'args': self.args, }) def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, ', '.join(str(x) for x in self.args)) class RegisteredSerializable(Serializable, metaclass=Meta): pass class Vector3D(RegisteredSerializable): def __init__(self, x, y, z): super().__init__(x, y, z) self.x, self.y, self.z = x, y, z v3 = Vector3D(10, -7, 3) print('Before: ', v3) data = v3.serialize() print('Serialized:', data) print('After: ', deserialize(data)) print(registry)
Die Verwendung von Metaklassen ist wie das Platzieren eines Hooks in der Klassenanweisung. Nachdem die Klassenanweisung verarbeitet wurde, wird der Hook sofort ausgelöst.
Die folgenden Sätze Filed.name
und Filed.name
mithilfe von Metaklassen.
class Field(object): def __init__(self): # These will be assigned by the metaclass. self.name = None self.internal_name = None def __get__(self, instance, instance_type): if instance is None: return self return getattr(instance, self.internal_name, '') def __set__(self, instance, value): setattr(instance, self.internal_name, value) class Meta(type): def __new__(meta, name, bases, class_dict): for key, value in class_dict.items(): if isinstance(value, Field): value.name = key value.internal_name = '_' + key cls = type.__new__(meta, name, bases, class_dict) return cls class DatabaseRow(object, metaclass=Meta): pass class BetterCustomer(DatabaseRow): first_name = Field() last_name = Field() prefix = Field() suffix = Field() foo = BetterCustomer() print('Before:', repr(foo.first_name), foo.__dict__) foo.first_name = 'Euler' print('After: ', repr(foo.first_name), foo.__dict__)
Das war's mit der Metaklassen-Zusammenfassung, und ich verstehe sie nicht ganz.
Ich hoffe, dass Python-Benutzer, die ein tiefes Verständnis dafür haben, eine Nachricht hinterlassen können.
Code von:
Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung von Metaklassen und ihrer Verwendung in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!