1A metaclass is the class of a class. A class defines how an instance of the class (i.e. an object) behaves while a metaclass defines how a class behaves. A class is an instance of a metaclass.
2
3While in Python you can use arbitrary callables for metaclasses (like Jerub shows), the better approach is to make it an actual class itself. type is the usual metaclass in Python. type is itself a class, and it is its own type. You won't be able to recreate something like type purely in Python, but Python cheats a little. To create your own metaclass in Python you really just want to subclass type.
4
5A metaclass is most commonly used as a class-factory. When you create an object by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass. Combined with the normal __init__ and __new__ methods, metaclasses therefore allow you to do 'extra things' when creating a class, like registering the new class with some registry or replace the class with something else entirely.
6
7When the class statement is executed, Python first executes the body of the class 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 __metaclass__ attribute of the class-to-be (if any) or the __metaclass__ global variable. The metaclass is then called with the name, bases and attributes of the class to instantiate it.
8
9However, metaclasses actually define the type 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. type.__subclasses__() is an example of a method on the type metaclass. You can also define the normal 'magic' methods, like __add__, __iter__ and __getattr__, to implement or change how the class behaves.
10
11Here's an aggregated example of the bits and pieces:
12
13def make_hook(f):
14 """Decorator to turn 'foo' method into '__foo__'"""
15 f.is_hook = 1
16 return f
17
18class MyType(type):
19 def __new__(mcls, name, bases, attrs):
20
21 if name.startswith('None'):
22 return None
23
24 # Go over attributes and see if they should be renamed.
25 newattrs = {}
26 for attrname, attrvalue in attrs.iteritems():
27 if getattr(attrvalue, 'is_hook', 0):
28 newattrs['__%s__' % attrname] = attrvalue
29 else:
30 newattrs[attrname] = attrvalue
31
32 return super(MyType, mcls).__new__(mcls, name, bases, newattrs)
33
34 def __init__(self, name, bases, attrs):
35 super(MyType, self).__init__(name, bases, attrs)
36
37 # classregistry.register(self, self.interfaces)
38 print "Would register class %s now." % self
39
40 def __add__(self, other):
41 class AutoClass(self, other):
42 pass
43 return AutoClass
44 # Alternatively, to autogenerate the classname as well as the class:
45 # return type(self.__name__ + other.__name__, (self, other), {})
46
47 def unregister(self):
48 # classregistry.unregister(self)
49 print "Would unregister class %s now." % self
50
51class MyObject:
52 __metaclass__ = MyType
53
54
55class NoneSample(MyObject):
56 pass
57
58# Will print "NoneType None"
59print type(NoneSample), repr(NoneSample)
60
61class Example(MyObject):
62 def __init__(self, value):
63 self.value = value
64 @make_hook
65 def add(self, other):
66 return self.__class__(self.value + other.value)
67
68# Will unregister the class
69Example.unregister()
70
71inst = Example(10)
72# Will fail with an AttributeError
73#inst.unregister()
74
75print inst + inst
76class Sibling(MyObject):
77 pass
78
79ExampleSibling = Example + Sibling
80# ExampleSibling is now a subclass of both Example and Sibling (with no
81# content of its own) although it will believe it's called 'AutoClass'
82print ExampleSibling
83print ExampleSibling.__mro__
84
1/*
2A metaclass is the class of a class. A class defines how an instance of the class (i.e. an object) behaves while a metaclass defines how a class behaves. A class is an instance of a metaclass.
3
4While in Python you can use arbitrary callables for metaclasses (like Jerub shows), the better approach is to make it an actual class itself. type is the usual metaclass in Python. type is itself a class, and it is its own type. You won't be able to recreate something like type purely in Python, but Python cheats a little. To create your own metaclass in Python you really just want to subclass type.
5
6A metaclass is most commonly used as a class-factory. When you create an object by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass. Combined with the normal __init__ and __new__ methods, metaclasses therefore allow you to do 'extra things' when creating a class, like registering the new class with some registry or replace the class with something else entirely.
7
8When the class statement is executed, Python first executes the body of the class 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 __metaclass__ attribute of the class-to-be (if any) or the __metaclass__ global variable. The metaclass is then called with the name, bases and attributes of the class to instantiate it.
9
10However, metaclasses actually define the type 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. type.__subclasses__() is an example of a method on the type metaclass. You can also define the normal 'magic' methods, like __add__, __iter__ and __getattr__, to implement or change how the class behaves.
11
12Here's an aggregated example of the bits and pieces:
13*/
14
15def make_hook(f):
16 """Decorator to turn 'foo' method into '__foo__'"""
17 f.is_hook = 1
18 return f
19
20class MyType(type):
21 def __new__(mcls, name, bases, attrs):
22
23 if name.startswith('None'):
24 return None
25
26 # Go over attributes and see if they should be renamed.
27 newattrs = {}
28 for attrname, attrvalue in attrs.iteritems():
29 if getattr(attrvalue, 'is_hook', 0):
30 newattrs['__%s__' % attrname] = attrvalue
31 else:
32 newattrs[attrname] = attrvalue
33
34 return super(MyType, mcls).__new__(mcls, name, bases, newattrs)
35
36 def __init__(self, name, bases, attrs):
37 super(MyType, self).__init__(name, bases, attrs)
38
39 # classregistry.register(self, self.interfaces)
40 print "Would register class %s now." % self
41
42 def __add__(self, other):
43 class AutoClass(self, other):
44 pass
45 return AutoClass
46 # Alternatively, to autogenerate the classname as well as the class:
47 # return type(self.__name__ + other.__name__, (self, other), {})
48
49 def unregister(self):
50 # classregistry.unregister(self)
51 print "Would unregister class %s now." % self
52
53class MyObject:
54 __metaclass__ = MyType
55
56
57class NoneSample(MyObject):
58 pass
59
60# Will print "NoneType None"
61print type(NoneSample), repr(NoneSample)
62
63class Example(MyObject):
64 def __init__(self, value):
65 self.value = value
66 @make_hook
67 def add(self, other):
68 return self.__class__(self.value + other.value)
69
70# Will unregister the class
71Example.unregister()
72
73inst = Example(10)
74# Will fail with an AttributeError
75#inst.unregister()
76
77print inst + inst
78class Sibling(MyObject):
79 pass
80
81ExampleSibling = Example + Sibling
82# ExampleSibling is now a subclass of both Example and Sibling (with no
83# content of its own) although it will believe it's called 'AutoClass'
84print ExampleSibling
85print ExampleSibling.__mro__
86