6618 votes

Que sont les métaclasses en Python ?

En Python, que sont les métaclasses et à quoi servent-elles ?

59voto

La version abrégée

Le site type(obj) permet d'obtenir le type d'un objet.

Le site type() d'une classe est son métaclasse .

Pour utiliser une métaclasse :

class Foo(object):
    __metaclass__ = MyMetaClass

type est sa propre métaclasse. La classe d'une classe est une métaclasse - le corps d'une classe est constitué des arguments passés à la métaclasse qui est utilisée pour construire la classe.

Ici vous pouvez lire comment utiliser les métaclasses pour personnaliser la construction des classes.

56voto

Mushahid Khan Points 2186

type est en fait un metaclass -- une classe qui crée une autre classe. La plupart des sites metaclass sont les sous-classes de type . Le site metaclass reçoit le new comme premier argument et donne accès à l'objet classe avec les détails mentionnés ci-dessous :

>>> 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:

Remarquez que la classe n'a été instanciée à aucun moment ; le simple fait de créer la classe a déclenché l'exécution de la commande metaclass .

44voto

espeed Points 2951

La meilleure explication sur les métaclasses que j'ai lue est "Metaclasses Demystified". http://cleverdevil.org/computing/78/ qui a été publié à l'origine dans Python Magazine.

EDIT : Voici une version archivée en attendant que le site de Jonathan soit réparé :

http://web.archive.org/web/20120503014702/http://cleverdevil.org/computing/78/

39voto

Xingzhou Liu Points 1005

Les classes Python sont elles-mêmes des objets - comme dans instance - de leur méta-classe.

La métaclasse par défaut, qui est appliquée lorsque vous déterminez des classes comme :

class foo:
    ...

Les méta-classes sont utilisées pour appliquer une règle à un ensemble de classes. Par exemple, supposons que vous construisiez un ORM pour accéder à une base de données, et que vous souhaitiez que les enregistrements de chaque table soient d'une classe associée à cette table (en fonction des champs, des règles de gestion, etc.), une utilisation possible des métaclasses est par exemple la logique du pool de connexion, qui est partagée par toutes les classes d'enregistrement de toutes les tables. Une autre utilisation est la logique de prise en charge des clés étrangères, qui implique plusieurs classes d'enregistrements.

lorsque vous définissez une métaclasse, vous sous-classez le type, et pouvez surcharger les méthodes magiques suivantes pour insérer votre logique.

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

Quoi qu'il en soit, ces deux crochets sont les plus couramment utilisés. le métaclassique est puissant, et ce qui précède est loin d'être une liste exhaustive des utilisations du métaclassique.

36voto

binbjz Points 246

La fonction type() peut retourner le type d'un objet ou créer un nouveau type,

Par exemple, nous pouvons créer une classe Hi avec la fonction type() et n'avons pas besoin d'utiliser cette méthode avec la classe Hi(object) :

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

En plus d'utiliser type() pour créer des classes de façon dynamique, vous pouvez contrôler le comportement de création des classes et utiliser des métaclasses.

Selon le modèle objet Python, la classe est l'objet, donc la classe doit être une instance d'une autre certaine classe. Par défaut, une classe Python est une instance de la classe type. C'est-à-dire que type est la métaclasse de la plupart des classes intégrées et la métaclasse des classes définies par l'utilisateur.

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']

La magie prendra effet lorsque nous avons passé des arguments de mots-clés dans la métaclasse, elle indique à l'interprète Python de créer la CustomList à travers ListMetaclass. nouveau (), à ce stade, nous pouvons modifier la définition de la classe, par exemple, et ajouter une nouvelle méthode, puis renvoyer la définition révisée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X