1. type()
1. Two ways to create classes
Method one
class MyClass(object): def func(self,name): print(name) myc = MyClass() print(MyClass, type(MyClass)) print(myc, type(myc))
We created a class called MyClass and instantiated this class to get its object myc
The above code prints the result as:
<class '__main__.MyClass'> <class 'type'> <__main__.MyClass object at 0x0288F8F0> <class '__main__.MyClass'>
The type() function can view the type of a type or variable. MyClass is a class, its type is type, and myc is an instance, its type is class MyClass.
We say that the definition of class is created dynamically at runtime, and the method to create class is to use the type() function.
The type() function can not only return the type of an object, but also create a new type. For example, we can create the MyClass class through the type() function without the definition of Class MyClass(object):
Method 2
Dynamically create classes
type(class name, tuple of parent class (can be empty for inheritance), dictionary of attributes (name and value))
def fn(self, name='world'): # Define the function first print('Hello, %s.' % name) MyClass = type('MyClass', (object,), {'func':fn}) # Create MyClass class and get a type class object# MyClass = type('MyClass', (object,), {'func':lambda self,name:name}) # Create MyClass class myc=MyClass() print(MyClass, type(MyClass)) print(myc, type(myc))
Print result:
<class '__main__.MyClass'> <class 'type'> <__main__.MyClass object at 0x0364B830> <class '__main__.MyClass'>
To create a class object, the type() function passes in 3 parameters in turn:
- The name of class;
- Inherited parent class collection, note that Python supports multiple inheritance. If there is only one parent class, don’t forget the single element writing method of tuple;
- The method name of class is bound to the function, here we bind the function fn to the method name func.
Classes created through the type() function are exactly the same as writing class directly, because when the Python interpreter encounters a class definition, it simply scans the syntax of the class definition and then calls the type() function to create a class.
type is the class that creates class objects. You can see this by checking the __class__ attribute. Everything in Python, note that I mean everything-is objects. This includes integers, strings, functions, and classes. They are all objects, and they are all created from a class (metaclass, default to type, and can also be customized). The type is also created by the type.
2. Metaclass
In addition to using type() to dynamically create classes, you can also use metaclass to control the creation behavior of the class.
metaclass, literally translated as metaclass, the simple explanation is:
After we define a class, we can create an instance based on this class, so: first define the class, and then create an instance.
But what if we want to create a class? Then you must create a class based on metaclass, so: first define the metaclass (when not customize it, type is used by default), and then create the class.
Connecting together means: first define metaclass, then you can create a class, and finally create an instance.
Therefore, metaclass allows you to create or modify classes. In other words, you can think of a class as an "instance" created by a metaclass.
By default, classes are constructed using type(). The class body is executed in a new namespace, and the class name is locally bound to the result of the type (name, base, namespace).
The class creation process can be customized by passing metaclass keyword parameters in the class definition row, or inherit from an existing class containing such parameters. In the following example, both MyClass and MySubclass are instances of Meta:
class Meta(type): pass class MyClass(metaclass=Meta): pass class MySubclass(MyClass): pass
Two ways to use metaclass
class MyType(type):# Customize a derived class of a type def __init__(self,*args,**kwargs): print('xx') super(MyType,self).__init__(*args,**kwargs) def __call__(cls, *args, **kwargs): obj = cls.__new__(cls,*args, **kwargs) cls.__init__(obj,*args, **kwargs) return obj def with_metaclass(base): return MyType("MyType2",(base,),{}) # Method 1class Foo(metaclass=MyType):# metaclass=MyType, that is, the Foo class is created by MyType. When the program runs and uses class Foo, it calls MyType's __init__ method to create Foo class def __init__(self,name): = name #Method 2 has been used in the source code of Flask's wtform# class Foo(with_metaclass(object)): # def __init__(self,name): # = name a=Foo('name')
Method 1: Ready-to-use class form
After executing the code, when class Foo is encountered, it declares that it wants to create a Foo class, and the type of the call is called.__init__
Method creates a class. Since here (metaclass=MyType), the Foo class creation method is specified, the type derived class MyType will be executed.__init__
Method, create Foo class, print 'xx' once
Generally speaking, if you want to use a class to implement metaclass, the class needs to inherit from type, and the type will usually be rewritten.
__new__
Method to control the creation process.Methods defined in metaclass will become class methods, and can be called directly through the class name
Method 2: Use function form
Constructing a function to return a derived class object of type, such as a derived class called type, requires 3 parameters: name, bases, attrs
- name: the name of the class
- bases: base class, usually tuple type
- attrs: dict type is the attribute or function of the class
metaclass principle
1. Basics
The principle of metaclass is actually as follows: after defining the class, when creating the class, the __new__ method of type is actually called to allocate memory space for this class. After creating it, the __init__ method of type is called to initialize (do some assignments, etc.). So all the magic of metaclass actually lies in this __new__ method.
Tell me about this method:__new__(cls, name, bases, attrs)
cls: The class to be created is similar to self, but self points to instance, where cls points to class
name: The name of the class, which is what we usually get with the class name.__name__.
bases: base class
attrs: dict of the attribute. The content of a dict can be a variable (class attribute) or a function (class method).
So in the process of creating a class, we can modify the values of name, bases, and attrs in this function to freely achieve our functions. The commonly used method of coordination here is
getattr and setattr (just an advice)
2. Search order
Metaclasses are determined by the following priority rules:
If the "metaclass" exists, it is used.
Otherwise, if there is at least one base class, it's metaclass (this looks for the class attribute first, and if not found, it's type).
Otherwise, if a global variable named metaclass exists, it will be used.
3. Three special methods: __init__, __new__, __call__
__new__
: The creation of an object is a static method, and the first parameter is cls. (Think of it, it cannot be self. The object has not been created yet, where does self come from?) It must have a return value and return the instantiated instance. It should be noted that you can return the parent class__new__()
The instances can also be directly used to object__new__()
The outgoing instance returns.__init__
: The initialization of the object is an instance method. The first parameter is self, and the self parameter is__new__()
The returned instance,__init__()
exist__new__()
On the basis of this, some other initialization actions can be completed.__init__()
No return value is required.__call__
: The object can be called, note that it is not a class, it is an object.
1. For __new__
class Bar(object): pass class Foo(object): def __new__(cls, *args, **kwargs): return Bar() print(Foo())
The print result is:
<__main__.Bar object at 0x0090F930>
As you can see, the output is a Bar object.
__new__
Methods are not necessary to be written in class definitions. If they are not defined, they will be called by default.object.__new__
Go to create an object. If defined, it will overwrite and use custom, so that the behavior of creating objects can be customized.
2. For __init__
class Person(object): def __init__(self, name, age): = name = age print('Execute __init__') def __new__(cls, *args, **kwargs): obj = object.__new__(cls) # Create an object print('Execute __new__ method') return obj p1 = Person('hc', 24) print(p1)
Print result:
Execute the __new__ method
Execute __init__
<__main__.Person object at 0x028EB830>
The __init__ method is usually used when initializing a class instance, but __init__ is actually not the first method to be called when instantiating a class. When using expressions like Persion(name, age) to instantiate a class, the first method called is actually the __new__ method. You can see from the print results
If __new__() does not return the instance of the current class cls correctly, __init__() will not be called, even the instance of the parent class will not work.
3. For __call__
Objects are provided by__call__(slef, *args ,**kwargs)
Methods can simulate the behavior of a function. If an object x provides the method, it can be used like a function, that is, x(arg1, arg2...) is equivalent to calling.x.__call__(self, arg1, arg2)
。
class Foo(object): def __call__(self): pass #No one answers the questions encountered during study? The editor has created a Python learning exchange group: 153708845f = Foo() #Class(), that is, the __call__ execution of the metaclassf() #Object(),That is, executeFooof__call__
4. The complete process of instantiating an object
class Foo(Bar): pass
When we write this code, Python does the following:
Is there a metaclass attribute in Foo? If so, Python will create a class object named Foo in memory through metaclass (I'm talking about class objects, please follow my thoughts). If Python does not find metaclass, it will continue to look for metaclass properties in Bar (parent class) and try to do the same thing as before. If Python cannot find metaclass in any parent class, it will look for metaclass in the module level and try to do the same. If metaclass is still not found, Python will use the built-in type to create this class object.
After reading the above passage several times, the question now is, what code can you place in the metaclass?
The answer is: you can create something of a class.
So what can be used to create a class?
Type, or anything that uses type or subclasses.
As an example, when we instantiate an object obj=Foo(), we will first execute the __new__ method of the Foo class. When we haven't written it, we will use the __new__ method of the parent class to create an object, and then execute the __init__ method (use your own if you have it, and use your own if you don't), and initialize the created object.
obj() will execute the __call__ method of Foo class, and if there is no, the parent class will be used.
We now know that a class is also an object, an object of a metaclass, that is, when we instantiate a class, we call the __call__ method of its metaclass.
Metaclass processing process: When defining a class, use a declaration or a default metaclass to create the class, find the type operation of the metaclass, get the parent class (the parent class of the metaclass declared by the class), call the __call__ function of the parent class, and in the __call__ function of the metaclass declared by the class to create an object (the function needs to return an object (referring to the class) instance), and then call the __init__ of the metaclass to initialize the object (here the object refers to the class because it is an object created by the metaclass), and finally return the class
1. Object is a class creation. When creating an object, the __init__ method of the class is automatically executed. Object() executes the __call__ method of the class
2. Class is created by type. When creating a class, the __init__ method of type is automatically executed. Class() executes the __call__ method of type (class __new__ method, class __init__ method)
The original type's __call__ should be the parameter structure should be:
metaname, clsname, baseclasses, attrs
Original type__new__
metaname, clsname, baseclasses, attrs
Original type__init__
class_obj, clsname, baseclasses, attrs
The __new__ and __init__ of the metaclass affect the behavior of creating class objects. The __call__ of the parent class controls the calls to the __new__ and __init__ of the child metaclass, which controls the creation and initialization of the class objects. The __new__ and __init__ of the parent class are controlled by higher levels,
Generally speaking, the original type is the original parent class, and its __new__ and __init__ are of universal significance, that is, they should allocate memory, initialize related information, etc.
The metaclass __call__ affects the behavior of creating instance objects of the class. At this time, if the class customizes __new__ and __init__, it can control the creation and initialization of object instances of the class.
__new__ and __init__ affect the behavior of creating objects. When these functions are in metaclasses, the class is affected; similarly, when these two functions are in ordinary classes, the instance of the object is affected.
__call__ affects the calling behavior of(). __call__ is called when creating a class, that is: class Test(object): __metaclass__=type. When defining a class, the class is created. At this time, the __call__ of the metaclass will be called. If the metaclass has inheritance, the __call__ of the parent class is executed when the child metaclass is defined.
If it is an object instantiated by a normal class, the call is the __call__ of the normal class
The above is a detailed explanation of the process of class creation and instantiation in Python. For more information about Python class creation and instantiation, please pay attention to my other related articles!