This article originated from personal public account: TechFlow, original is not easy, for attention


Today is the 16th article in our Python series on metaclasses in Python.

Metaclass is an advanced use of Python, which is perfectly normal if you have never seen the term or heard of the concept before, both because it is infrequently used and because it is relatively difficult to understand. So much so that many Python developers don’t understand it very well, and as a result there isn’t much material out there. I also read some great code to open the door to this new world.

Everything is an object

As we explained earlier, in Python everything is an object, and notice, everything is an object. We all know that an object is the result of an instantiation of a class, and we can simply compare classes and objects to molds and artifacts. Molds are classes, and products based on molds are objects.

This analogy is close, but not perfect. Because in fact, a mold can make multiple products, a product only one mold. But programming languages are different because classes can be inherited from one another and multiple inheritance, which means that an object can correspond to more than one class. So the analogy is not particularly appropriate, but the class-object relationship is correct.

But that raises a question. Since everything in Python is an object, is a class really an object? So a mold is actually the product of another mold? Similarly, the mold of this mold is also the product of another mold, so what will happen if we keep asking?

We can use the _class__ keyword to check the type of a variable, so we can call it repeatedly to check the relationship:


As you can see from the above figure, num is a variable of type int. We continue to look at the type of the type int and get the type type. When we check the type of type, we will find that we still get a type of type.

So we can see that type is the metaclass used in Python to create all classes, and is the mold for all molds. In Python, we call aclass of aclass a metaclass. So type is a built-in metaclass in Python, and we can create our own metaclass. With metaclasses, the object we create is also a class, not an instance.

Dynamically creating classes

Now that you understand that Type is the foundation of all classes, it’s easy to look at dynamic classes. Dynamic classes are one of the biggest features of dynamic languages, and as a typical dynamic language, Python naturally supports dynamic creation of types.

One way to create dynamic types in Python is through the type keyword. The type function is used to query the type of an object.

This is actually another use of type, creating a class as a metaclass. In this usage, the type function takes three arguments, the name of the type, the tuple of the superclass, and a dictionary. Except for the first parameter, the next two parameters can be null. Let’s look at an example:


Note that type returns a class, not an instance. So we can also create instances with it:

hello = Hello()
Copy the code

This creates the simplest empty class, which has nothing and is equivalent to the following code.

class Hello:
    pass
Copy the code

We can also populate the class with properties and methods in the type argument:

def hello_world(self):
    print('hello')
    
Hello = type('Hello', (), {'hello':hello_world, 'num': 3})
Copy the code

So we create a method for the Hello class called Hello with a property num equals 3. We can call it:


That is, we can use Type to define our own classes according to our needs, except that type can both get the type of the object and create a new class, which may seem a little counterintuitive, but it actually makes sense. In Python we create a string by calling STR, an integer by calling int, and an object of class by calling type.

Implementation inheritance

As we said earlier, when we create a class using Type, we can also pass in a tuple of the parent class to implement class inheritance.

For example, we create a class called World that inherits the Hello class created by type and adds an additional function to it:

def say_world(self):
    print('World')
    
World = type('World', (Hello, ), {'world': say_world})
Copy the code

Note that the second argument passed in here is the tuple of the parent class. Since it is a tuple, when there is only one element, we need to add a comma to indicate that it is a tuple. This creates a class that looks exactly like the static class defined by class:


That is, we can implement functions first and then assemble them into new classes according to the needs of the task. Obviously, this is much more flexible than traditional C++ and statically typed languages like Java.

conclusion

It is possible to create dynamically created classes using Type, but this is not very convenient and many advanced functions are difficult to implement. For a simple example, let’s say we want to dynamically add some dynamic methods to an existing class to generate a new class. It’s hard to do with type. It is also true that Type is not the main use of Python metaclass; metaclass is king, but due to space constraints, this will be in the next article.

Of course, metaclass is such an advanced usage that Python’s founders say 99% of Python programmers don’t need to use it. So if you find it hard to understand, don’t worry, just know the concept.

That’s all for today. If you like this article, please follow it, give me a little encouragement, and get more articles conveniently.