What are metaclasses? What do you use them for?
|
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. While in Python you can use arbitrary callables for metaclasses (like Jerub shows), the more useful approach is actually to make it an actual class itself. ' 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 When the ' However, 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. Here's an aggregated example of the bits and pieces:
|
|||||||||||||||||
|
Classes as objectsBefore understanding metaclasses, you need to master classes in Python. And Python has a very peculiar idea of what classes are, borrowed from the Smalltalk language. In most languages, classes are just pieces of code that describe how to produce an object. That's kinda true in Python too:
But classes are more than that in Python. Classes are objects too. Yes, objects. As soon as you use the keyword
creates in memory an object with the name "ObjectCreator". This object (the class) is itself capable of creating objects (the instances), and this is why it's a class. But still, it's an object, and therefore:
e.g.:
Creating classes dynamicallySince classes are objects, you can create them on the fly, like any object. First, you can create a class in a function using
But it's not so dynamic, since you still have to write the whole class yourself. Since classes are objects, they must be generated by something. When you use the Remember the function
Well, (I know, it's silly that the same function can have two completely different uses according to the parameters you pass to it. It's an issue due to backwards compatibility in Python)
e.g.:
can be created manually this way:
You'll notice that we use "MyShinyClass" as the name of the class and as the variable to hold the class reference. They can be different, but there is no reason to complicate things.
Can be translated to:
And used as a normal class:
And of course, you can inherit from it, so:
would be:
Eventually you'll want to add methods to your class. Just define a function with the proper signature and assign it as an attribute.
You see where we are going: in Python, classes are objects, and you can create a class on the fly, dynamically. This is what Python does when you use the keyword What are metaclasses (finally)Metaclasses are the 'stuff' that creates classes. You define classes in order to create objects, right? But we learned that Python classes are objects. Well, metaclasses are what create these objects. They are the classes' classes, you can picture them this way:
You've seen that
It's because the function Now you wonder why the heck is it written in lowercase, and not Well, I guess it's a matter of consistency with You see that by checking the Everything, and I mean everything, is an object in Python. That includes ints, strings, functions and classes. All of them are objects. And all of them have been created from a class:
Now, what is the
So, a metaclass is just the stuff that creates class objects. You can call it a 'class factory' if you wish.
The
|
|
@eddy147: sorry for being pedantic but Javascript has prototypes not classes.
–
Erik Allik
Aug 2 '11 at 9:53
|
||
|
Class Bar(object) inherits from
object . Python introduced new classes features and found this way to make it backward compatible. Unless you are dealing with a very old Python version, you always want to inherit from object because you'll get the new class behavior with it. In Python 3, all classes are going to be new classes and you won't need to do this anymore.
–
e-satis
Aug 8 '11 at 19:20
|
||
|
|||
|
I read this and think of the famous "There are lies, damned lies, and then there is statistics", but instead think of it as "there are hacks, tricks, voodoo magic, dark arts, and then there are Python metaclasses". Amazing write-up of an extremely complicated topic.
–
Adam Parkin
Feb 29 '12 at 20:08
|
||
|
All other articles on the net are TL;DR. And this is why nobody understood them. And this is why this article is such a success. I'm not sure putting any kind of short explanation would help anybody.
–
e-satis
Aug 26 '13 at 14:58
|
Metaclasses are the secret sauce that make 'class' work. The default metaclass for a new style object is called 'type'.
Metaclasses take 3 args. 'name', 'bases' and 'dict' Here is where the secret starts. Look for where name, bases and the dict come from in this example class definition.
Lets define a metaclass that will demonstrate how 'class:' calls it.
And now, an example that actually means something, this will automatically make the variables in the list "attributes" set on the class, and set to None.
Note that the magic behaviour that 'Initalised' gains by having the metaclass init_attributes is not passed onto a subclass of Initalised. Here is an even more concrete example, showing how you can subclass 'type' to make a metaclass that performs an action when the class is created. This is quite tricky:
|
|||||||||
|
One use for metaclasses is adding new properties and methods to an instance automatically. For example, if you look at Django models, their definition looks a bit confusing. It looks as if you are only defining class properties:
However, at runtime the Person objects are filled with all sorts of useful methods. See the source for some amazing metaclassery. |
|||
|
I think the ONLamp introduction to metaclass programming is well written and gives a really good introduction to the topic despite being several years old already. http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html In short: A class is a blueprint for the creation of an instance, a metaclass is a blueprint for the creation of a class. It can be easily seen that in Python classes need to be first-class objects too to enable this behavior. I've never written one myself, but I think one of the nicest uses of metaclasses can be seen in the Django framework. The model classes use a metaclass approach to enable a declarative style of writing new models or form classes. While the metaclass is creating the class, all members get the possibility to customize the class itself. The thing that's left to say is: If you don't know what metaclasses are, the probability that you will not need them is 99%. |
||||
|
Others have explained how metaclasses work and how they fit into the Python type system. Here's an example of what they can be used for. In a testing framework I wrote, I wanted to keep track of the order in which classes were defined, so that I could later instantiate them in this order. I found it easiest to do this using a metaclass.
Anything that's a subclass of |
||||
|
The best metaclass explanation I have read is "Metaclasses Demystified" http://cleverdevil.org/computing/78/, which originally appeared in Python Magazine. EDIT: Here's an archived version of it until Jonathan's site is fixed: https://waybackassets.bk21.net/20120503014702/http://cleverdevil.org/computing/78/ |
|||||
|
I had a really complicated problem, that probably could have been solved differently, but I chose to solve it using a metaclass. Because of the complexity, it is one of the few modules I have written where the comments in the module surpass the amount of code that has been written. Here it is...
|
||||
|
Nice explanation of Python classes, objects, and metaclasses: http://www.cafepy.com/article/python_types_and_objects/python_types_and_objects.html |
|||
|
protected by missingfaktor Oct 18 '12 at 18:42
Thank you for your interest in this question.
Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.
Would you like to answer one of these unanswered questions instead?