7371 Stimmen

Was sind Metaklassen in Python?

Was sind Metaklassen in Python und wofür werden sie verwendet?

65voto

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.

60voto

Mushahid Khan Punkte 2767

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 .

43voto

Xingzhou Liu Punkte 1415

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.

41voto

binbjz Punkte 741

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.

30voto

Andy Jazz Punkte 34407

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'

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X