Sure, classes are objects. You can run all the same methods on classes that you can run on object. Look, they each have their own ID in the symbol table.
But I've already told you: classes store methods. They're different. Now I know you're probably a bit confused wondering, "If a class is an object, but objects are built on classes, isn't there a big confusing infinite cycle here that you're not explaining?
No, there's not. I hate to break it to you, but a class isn't really an object. From Ruby's source code:. But let me reassure you. To a Ruby programmer, a class is an object. Because it meets the two big criteria: you can store instance variables in a class and it is descended from the Object class. That's it.
The Object class sits at the very head of the table and comes down to participate only when it has methods that can't be found anywhere else. The term metaclass is supposed mean "a class which defines classes. Look at how you can add a method in the Class class and then use it in class definitions. Which prints Please no more attributes today.
You're constantly defining and redefining classes in Ruby. It's not meta, it's just part of the code. Classes hold methods. How can you complicate that? Since the earlier definition doesn't really work, I like to think of the Ruby metaclass as "a class which an object uses to redefine itself. But sometimes you may want an object to have some methods.
Sometimes that's your answer to a problem. You can't do that. But Matz has given us metaclasses which are good enough. In the YAML library, you can customize the properties shown when an object is output. This is handy if you want to dump one specific object with a certain style of YAML without effecting every object from that class.
In the above example, only the object in the m variable will be output with its properties in order. Sometimes we may want to display a certain string one way without needing to modify the String class which affects every string in your code.
It's stored in a metaclass. The metaclass stores methods for the object and sits right in the inheritance chain. Ruby calls these virtual classes.
Notice the result of m. When an object finds methods in an attached metaclass, these methods are referred to as the object's singleton methods rather than the object's metaclass' instance methods if you get my drift. It's much easier to see metaclasses when you're using the metaclass method. But this makes it much simpler. Check out those frivolous metaclasses we're creating.
So what can we do with a metaclass of a metaclass? That includes integers, strings, functions and classes. All of them are objects. And all of them have been created from a class:. You write class Foo object first, but the class object Foo is not created in memory yet.
If it finds it, it will use it to create the object class Foo. If it doesn't, it will use type to create the class. The behavior of metaclasses however stays largely the same. One thing added to metaclasses in Python 3 is that you can also pass attributes as keyword-arguments into a metaclass, like so:.
Imagine a stupid example, where you decide that all classes in your module should have their attributes written in uppercase. This way, all classes of this module will be created using this metaclass, and we just have to tell the metaclass to turn all attributes to uppercase. Let's rewrite the above, but with shorter and more realistic variable names now that we know what they mean:.
You may have noticed the extra argument cls. Just like you have self for ordinary methods which receive the instance as the first parameter, or the defining class for class methods. But this is not proper OOP. Let's do that instead:. We can make it even cleaner by using super , which will ease inheritance because yes, you can have metaclasses, inheriting from metaclasses, inheriting from type :. Indeed, metaclasses are especially useful to do black magic, and therefore complicated stuff.
But by themselves, they are simple:. If you wonder whether you need them, you don't the people who actually need them to know with certainty that they need them and don't need an explanation about why. The main use case for a metaclass is creating an API. A typical example of this is the Django ORM. It allows you to define something like this:. It won't return an IntegerField object. It will return an int , and can even take it directly from the database. This is possible because models.
Django makes something complex look simple by exposing a simple API and using metaclasses, recreating code from this API to do the real job behind the scenes. Everything is an object in Python, and they are all either instance of classes or instances of metaclasses. This is not something you could reproduce in pure Python, and is done by cheating a little bit at the implementation level.
Secondly, metaclasses are complicated. You may not want to use them for very simple class alterations. You can change classes by using two different techniques:. A metaclass is the class of a class. A class defines how an instance of the class i. A class is an instance of a metaclass. While in Python you can use arbitrary callables for metaclasses like Jerub shows , the better approach is to make it an actual class itself.
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. A 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.
When 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 then called with the name, bases and attributes of the class to instantiate it. 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. Note, this answer is for Python 2. Metaclasses are the secret sauce that make 'class' work.
The default metaclass for a new style object is called 'type'. Metaclasses take 3 args. Here is where the secret starts. Look for where name, bases and the dict come from in this example class definition.
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.
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:. 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. 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.
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.
TLDR: A metaclass instantiates and defines behavior for a class just like a class instantiates and defines behavior for an instance. The above should look familiar. Well, where does Class come from? It's an instance of a metaclass also pseudocode :. In real code, we can pass the default metaclass, type , everything we need to instantiate a class and we get a class:. Likewise, when we define a class explicitly with the default metaclass, type , we instantiate it:.
When you write a class definition and Python executes it, it uses a metaclass to instantiate the class object which will, in turn, be used to instantiate instances of that class. Just as we can use class definitions to change how custom object instances behave, we can use a metaclass class definition to change the way a class object behaves.
What can they be used for? From the docs :. The potential uses for metaclasses are boundless. Nevertheless, it is usually encouraged for users to avoid using metaclasses unless absolutely necessary. It is the same as functionally calling type with the appropriate arguments and assigning the result to a variable of that name:. For example:. If, for example, we want to know in what order a class's methods are created in, we could provide an ordered dict as the namespace of the class.
And now we have a record of the order in which these methods and other class attributes were created:. Note, this example was adapted from the documentation - the new enum in the standard library does this. So what we did was instantiate a metaclass by creating a class.
We can also treat the metaclass as we would any other class. It has a method resolution order:. And it has approximately the correct repr which we can no longer eval unless we can find a way to represent our functions. You must return an instance of whatever namespace you choose.
Say you want some simple validation code to run on your attributes -- like it must always be an int or a str. Without a metaclass, your class would look something like:. As you can see, you have to repeat the name of the attribute twice. This makes typos possible along with irritating bugs.
Note : This example is simple enough it could have also been accomplished with a class decorator, but presumably an actual metaclass would be doing much more. If you've done Python programming for more than a few months you'll eventually stumble upon code that looks like this:.
But as we've seen from previous answers a class itself is an instance of a metaclass, so when we use the class as a callable i. Let's study the method call chain from specifically the perspective of creating an instance of a class. This is a metaclass that logs exactly the moment before an instance is created and the moment it's about to return it.
Observe that the code above doesn't actually do anything more than logging the tasks. Each method delegates the actual work to its parent's implementation, thus keeping the default behavior. It's also the one that ultimately returns the instance. Over the course of its execution it could actually return an object that hasn't been touched by either of these methods. Take for example this approach to the singleton pattern:. This is a case where I saw metaclass as a solution to my problem: 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 The class of a class is a metaclass-- the body of a class is the arguments passed to the metaclass that is used to construct the class. Here you can read about how to use metaclasses to customize class construction. Most metaclass are the subclasses of type. The metaclass receives the new class as its first argument and provide access to class object with details as mentioned below:.
Notice that the class was not instantiated at any time; the simple act of creating the class triggered execution of the metaclass. For example, suppose you're building an ORM to access a database, and you want records from each table to be of a class mapped to that table based on fields, business rules, etc..
Another use is logic to to support foreign keys, which involves multiple classes of records. In addition to using type to create classes dynamically, you can control creation behavior of class and use metaclass. According to the Python object model, the class is the object, so the class must be an instance of another certain class.
By default, a Python class is instance of the type class. That is, type is metaclass of most of the built-in classes and metaclass of user-defined classes. Magic will take effect when we passed keyword arguments in metaclass, it indicates the Python interpreter to create the CustomList through ListMetaclass.
In addition to the published answers I can say that a metaclass defines the behaviour for a class. So, you can explicitly set your metaclass. Instances are created using a constructor, a block of code that specifies what should happen when memory is allocated for an object.
However, when you take a close look at arguments passed to the constructor, you will notice that the first argument is always self. Well…it is. It is not responsible for creating an object instance but for instantiating its state.
This time we have cls as the first argument instead of self. The actual class is passed to the constructor of the object. But should that even be possible? Well, of course we did. Using the built-in id method, however, will return the memory address of our class.
Now it will get a little weird. Looks like the class of our Dog class is type It may look very similar to the built-in method type , that we use to acquire the type of an object. When we are in trouble, Python has another useful built-in method for us to clear things up. Oh well, they had their reasons. Our built-in type method is a metaclass - a class that is used as a blueprint to create classes.
What is a class of a metaclass? All classes in Python by default have type as a metaclass. A metaclass is then used to create a class that is then used to create objects. But what can we use this knowledge for? Firstly, we can use the second functionality of type to do something that is unheard of in most other programming languages.
0コメント