Heim  >  Artikel  >  Backend-Entwicklung  >  Detaillierte Erklärung von Metaklassen und ihrer Verwendung in Python

Detaillierte Erklärung von Metaklassen und ihrer Verwendung in Python

巴扎黑
巴扎黑Original
2017-07-20 09:30:331506Durchsuche

1. Verwenden Sie die Metaklasse, um Unterklassen zu überprüfen.

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

2. Registrieren Sie Unterklassen mit Metaklassen

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)

3. Verwenden Sie Metaklassen, um Klassenattribute zu kommentieren.

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!

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