Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>A metaclass is the class of a class. Like a class defines how an instance of the class behaves, a metaclass defines how a class behaves. A class is an instance of a metaclass.</p> <p><a href="https://i.stack.imgur.com/QQ0OK.png" rel="noreferrer"><img src="https://i.stack.imgur.com/QQ0OK.png" alt="metaclass diagram"></a></p> <p>While in Python you can use arbitrary callables for metaclasses (like <a href="https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python/100037#100037">Jerub</a> shows), the more useful approach is actually to make it an actual class itself. <code>type</code> is the usual metaclass in Python. In case you're wondering, yes, <code>type</code> is itself a class, and it is its own type. You won't be able to recreate something like <code>type</code> purely in Python, but Python cheats a little. To create your own metaclass in Python you really just want to subclass <code>type</code>.</p> <p>A metaclass is most commonly used as a class-factory. Like you create an instance of the class by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass. Combined with the normal <code>__init__</code> and <code>__new__</code> methods, metaclasses therefore allow you to do 'extra things' when creating a class, like registering the new class with some registry, or even replace the class with something else entirely.</p> <p>When the <code>class</code> statement is executed, Python first executes the body of the <code>class</code> statement as a normal block of code. The resulting namespace (a dict) holds the attributes of the class-to-be. The metaclass is determined by looking at the baseclasses of the class-to-be (metaclasses are inherited), at the <code>__metaclass__</code> attribute of the class-to-be (if any) or the <code>__metaclass__</code> global variable. The metaclass is then called with the name, bases and attributes of the class to instantiate it.</p> <p>However, metaclasses actually define the <em>type</em> of a class, not just a factory for it, so you can do much more with them. You can, for instance, define normal methods on the metaclass. These metaclass-methods are like classmethods, in that they can be called on the class without an instance, but they are also not like classmethods in that they cannot be called on an instance of the class. <code>type.__subclasses__()</code> is an example of a method on the <code>type</code> metaclass. You can also define the normal 'magic' methods, like <code>__add__</code>, <code>__iter__</code> and <code>__getattr__</code>, to implement or change how the class behaves.</p> <p>Here's an aggregated example of the bits and pieces:</p> <pre><code>def make_hook(f): """Decorator to turn 'foo' method into '__foo__'""" f.is_hook = 1 return f class MyType(type): def __new__(mcls, name, bases, attrs): if name.startswith('None'): return None # Go over attributes and see if they should be renamed. newattrs = {} for attrname, attrvalue in attrs.iteritems(): if getattr(attrvalue, 'is_hook', 0): newattrs['__%s__' % attrname] = attrvalue else: newattrs[attrname] = attrvalue return super(MyType, mcls).__new__(mcls, name, bases, newattrs) def __init__(self, name, bases, attrs): super(MyType, self).__init__(name, bases, attrs) # classregistry.register(self, self.interfaces) print "Would register class %s now." % self def __add__(self, other): class AutoClass(self, other): pass return AutoClass # Alternatively, to autogenerate the classname as well as the class: # return type(self.__name__ + other.__name__, (self, other), {}) def unregister(self): # classregistry.unregister(self) print "Would unregister class %s now." % self class MyObject: __metaclass__ = MyType class NoneSample(MyObject): pass # Will print "NoneType None" print type(NoneSample), repr(NoneSample) class Example(MyObject): def __init__(self, value): self.value = value @make_hook def add(self, other): return self.__class__(self.value + other.value) # Will unregister the class Example.unregister() inst = Example(10) # Will fail with an AttributeError #inst.unregister() print inst + inst class Sibling(MyObject): pass ExampleSibling = Example + Sibling # ExampleSibling is now a subclass of both Example and Sibling (with no # content of its own) although it will believe it's called 'AutoClass' print ExampleSibling print ExampleSibling.__mro__ </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload