Was sind Metaklassen in Python und wofür werden sie verwendet?
Antworten
Zu viele Anzeigen?Die Kurzfassung
Le site type(obj)
ermittelt den Typ eines Objekts.
Le site type()
einer Klasse ist ihre Metaklasse .
Um eine Metaklasse zu verwenden:
class Foo(object):
__metaclass__ = MyMetaClass
type
ist eine eigene Metaklasse. Die Klasse einer Klasse ist eine Metaklasse - der Körper einer Klasse sind die Argumente, die an die Metaklasse übergeben werden, die zur Konstruktion der Klasse verwendet wird.
Hier können Sie nachlesen, wie Sie Metaklassen zur Anpassung der Klassenkonstruktion verwenden können.
type
ist eigentlich ein metaclass
-- eine Klasse, die andere Klassen erzeugt. Die meisten metaclass
sind die Unterklassen von type
. Die metaclass
erhält die new
Klasse als erstes Argument an und bietet Zugriff auf das Klassenobjekt mit den unten genannten Details:
>>> class MetaClass(type):
... def __init__(cls, name, bases, attrs):
... print ('class name: %s' %name )
... print ('Defining class %s' %cls)
... print('Bases %s: ' %bases)
... print('Attributes')
... for (name, value) in attrs.items():
... print ('%s :%r' %(name, value))
...
>>> class NewClass(object, metaclass=MetaClass):
... get_choch='dairy'
...
class name: NewClass
Bases <class 'object'>:
Defining class <class 'NewClass'>
get_choch :'dairy'
__module__ :'builtins'
__qualname__ :'NewClass'
Note:
Beachten Sie, dass die Klasse zu keinem Zeitpunkt instanziiert wurde; der einfache Akt der Erstellung der Klasse löste die Ausführung der metaclass
.
Python-Klassen sind selbst Objekte - wie in Instanz - ihrer Meta-Klasse.
Die Standard-Metaklasse, die angewendet wird, wenn Sie Klassen als festlegen:
class foo:
...
Metaklassen werden verwendet, um eine Regel auf eine ganze Gruppe von Klassen anzuwenden. Angenommen, Sie bauen einen ORM für den Zugriff auf eine Datenbank und möchten, dass Datensätze aus jeder Tabelle einer Klasse zugeordnet werden (auf der Grundlage von Feldern, Geschäftsregeln usw.), dann ist eine mögliche Verwendung von Metaklassen beispielsweise die Logik des Verbindungspools, die von allen Klassen von Datensätzen aus allen Tabellen gemeinsam genutzt wird. Eine andere Verwendung ist die Logik zur Unterstützung von Fremdschlüsseln, die mehrere Klassen von Datensätzen umfasst.
Wenn Sie eine Metaklasse definieren, können Sie den Typ unterordnen und die folgenden magischen Methoden überschreiben, um Ihre Logik einzufügen.
class somemeta(type):
__new__(mcs, name, bases, clsdict):
"""
mcs: is the base metaclass, in this case type.
name: name of the new class, as provided by the user.
bases: tuple of base classes
clsdict: a dictionary containing all methods and attributes defined on class
you must return a class object by invoking the __new__ constructor on the base metaclass.
ie:
return type.__call__(mcs, name, bases, clsdict).
in the following case:
class foo(baseclass):
__metaclass__ = somemeta
an_attr = 12
def bar(self):
...
@classmethod
def foo(cls):
...
arguments would be : ( somemeta, "foo", (baseclass, baseofbase,..., object), {"an_attr":12, "bar": <function>, "foo": <bound class method>}
you can modify any of these values before passing on to type
"""
return type.__call__(mcs, name, bases, clsdict)
def __init__(self, name, bases, clsdict):
"""
called after type has been created. unlike in standard classes, __init__ method cannot modify the instance (cls) - and should be used for class validaton.
"""
pass
def __prepare__():
"""
returns a dict or something that can be used as a namespace.
the type will then attach methods and attributes from class definition to it.
call order :
somemeta.__new__ -> type.__new__ -> type.__init__ -> somemeta.__init__
"""
return dict()
def mymethod(cls):
""" works like a classmethod, but for class objects. Also, my method will not be visible to instances of cls.
"""
pass
Jedenfalls sind diese beiden die am häufigsten verwendeten Haken. Metaclassing ist mächtig, und die obige Liste ist bei weitem nicht erschöpfend.
Die Funktion type() kann den Typ eines Objekts zurückgeben oder einen neuen Typ erstellen,
Wir können z. B. eine Klasse Hi mit der Funktion type() erstellen und müssen diesen Weg nicht mit der Klasse Hi(object) gehen:
def func(self, name='mike'):
print('Hi, %s.' % name)
Hi = type('Hi', (object,), dict(hi=func))
h = Hi()
h.hi()
Hi, mike.
type(Hi)
type
type(h)
__main__.Hi
Zusätzlich zur Verwendung von type(), um Klassen dynamisch zu erstellen, können Sie das Erstellungsverhalten von Klassen steuern und Metaklassen verwenden.
Nach dem Python-Objektmodell ist die Klasse das Objekt, also muss die Klasse eine Instanz einer anderen bestimmten Klasse sein. Standardmäßig ist eine Python-Klasse eine Instanz der Klasse type. Das heißt, type ist die Metaklasse der meisten eingebauten Klassen und die Metaklasse der benutzerdefinierten Klassen.
class ListMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value)
return type.__new__(cls, name, bases, attrs)
class CustomList(list, metaclass=ListMetaclass):
pass
lst = CustomList()
lst.add('custom_list_1')
lst.add('custom_list_2')
lst
['custom_list_1', 'custom_list_2']
Magic wird wirksam, wenn wir Schlüsselwortargumente in der Metaklasse übergeben, es zeigt dem Python-Interpreter an, die CustomList durch ListMetaclass zu erstellen. neu () können wir an dieser Stelle die Klassendefinition ändern, z. B. eine neue Methode hinzufügen, und dann die überarbeitete Definition zurückgeben.
Ergänzend zu den veröffentlichten Antworten kann ich sagen, dass ein metaclass
definiert das Verhalten für eine Klasse. Sie können also Ihre Metaklasse explizit festlegen. Wann immer Python ein Schlüsselwort class
dann beginnt es mit der Suche nach dem metaclass
. Wenn er nicht gefunden wird, wird der Standard-Metaklassentyp verwendet, um das Objekt der Klasse zu erstellen. Die Verwendung der __metaclass__
Attribut, können Sie die metaclass
Ihrer Klasse:
class MyClass:
__metaclass__ = type
# write here other method
# write here one more method
print(MyClass.__metaclass__)
Die Ausgabe sieht dann so aus:
class 'type'
Und natürlich können Sie auch Ihre eigenen metaclass
um das Verhalten aller Klassen zu definieren, die mit Ihrer Klasse erstellt werden.
Zu diesem Zweck wird Ihr Standard metaclass
Typklasse geerbt werden, da dies die wichtigste metaclass
:
class MyMetaClass(type):
__metaclass__ = type
# you can write here any behaviour you want
class MyTestClass:
__metaclass__ = MyMetaClass
Obj = MyTestClass()
print(Obj.__metaclass__)
print(MyMetaClass.__metaclass__)
Die Ausgabe wird sein:
class '__main__.MyMetaClass'
class 'type'