Class and object creation process (metaclass, __new__, __init__, __call__), __new____init__
First, type () 1, two ways to create a class
class MyClass (object):
def func (self, name):
print (name)
myc = MyClass ()
print (MyClass, type (MyClass))
print (myc, type (myc))
We create a class named MyClass and instantiate this class to get its object myc
The above code prints the result:
<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 h is an instance, and its type is class myc.
We say that the definition of a class is created dynamically at runtime, and the way to create a class is to use the type () function.
The type () function can return both the type of an object and create a new type. For example, we can create a MyClass class through the type () function without having to define Class MyClass (object) ...:
Way two
Creating classes dynamically
type (class name, tuple of parent class (can be empty for inheritance), dictionary containing attributes (name and value))
def fn (self, name = 'world'): # Define function first
print ('Hello,% s.'% name)
MyClass = type ('MyClass', (object,), ('func': fn)) # Create a MyClass class and get a type object
# MyClass = type ('MyClass', (object,), ('func': lambda self, name: name)) # Create a MyClass class
myc = MyClass ()
print (MyClass, type (MyClass))
print (myc, type (myc))
Print results:
<class '__main __. MyClass'> <class 'type'>
<__ main __. MyClass object at 0x0364B830> <class '__main __. MyClass'>
To create a class object, the type () function passes 3 parameters in order:
The class created by the type () function is exactly the same as writing the 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 the class.
type is the class that creates the class object. You can see this by checking the __class__ attribute. Everything in Python, note, I mean everything-objects. This includes integers, strings, functions, and classes. They are all objects, and they are all created from a class (metaclass, default type, or customized). type is also created by type. .
Second, metaclass
In addition to dynamically creating classes using type (), to control the creation of classes, you can also use metaclasses.
Metaclass, literally translated into 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 the instance.
But what if we want to create a class? Then you must create a class according to the metaclass, so: first define the metaclass (if not customized, the default type), and then create the class.
The connection is: first define the metaclass, 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.
Two ways to use metaclass
class MyType (type): # Customize a derived class of 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 one
class Foo (metaclass = MyType): # metaclass = MyType, which specifies that the Foo class is created by MyType. When the program is run and class Foo is used, the __init__ method of MyType is called to create the Foo class
def __init __ (self, name):
self.name = name
#Method two used in the source code of Flask's wtform
# class Foo (with_metaclass (object)):
# def __init __ (self, name):
# self.name = name
a = Foo ('name')
Method 1: the form of a ready-to-use class
After executing the code, when you encounter class Foo, you declare that you want to create a Foo class, and you will call the type's __init__ method to create the class. Here (metaclass = MyType), which specifies the way to create the Foo class, it Execute the __init__ method of the derived class MyType of type, create the Foo class, and print 'xx' once
* In general, if you want to use a class to implement a metaclass, the class needs to inherit from type, and the __new__ method of type is usually overridden to control the creation process.
* The method defined in the metaclass will become the method of the class, which can be called directly by the class name
Method 2: Use the form of a function
Build a function that returns a derived object of type, such as a derived class called type, which requires 3 parameters: name, bases, attrs
Name: the name of the class
Bases: base class, usually tuple type
Attrs: dict type, which is a class attribute or function
metaclass principle 1. basics
The principle of metaclass is actually this: When a class is defined, when the class is created, the type __new__ method is called to allocate memory space for the class. After the class is created, the type __init__ method is initialized (do Some assignments, etc.). So all the magic of the metaclass is actually in this __new__ method.
Talk about this method: __new __ (cls, name, bases, attrs)
cls: the class to be created, similar to self, but self refers to instance, and here cls refers to class
name: the name of the class, which is what we usually get with the class name .__ name__.
bases: base classes
attrs: a dict of attributes. 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 achieve our function freely. The commonly used method here is
getattr and setattr (just an advice)
2. Search order
Metaclasses are determined by the following precedence rules:
If the "metaclass" exists, it is used.
Otherwise, if there is at least one base class, its metaclass is used (this looks for the class attribute first, and if it is not found, its type is used).
Otherwise, if a global variable named metaclass exists, it will be used.
Three, __init__, __new__, __call__ three special methods
__new__: The creation of the object is a static method, the first parameter is cls. (Think about it too, it can't be self, the object hasn't been created yet, where's the self)
It must have a return value to return the instantiated instance. Note that you can return the instance of the parent class __new __ (), or you can directly return the instance of object __new __ ().
__init__: The initialization of the object is an instance method. The first parameter is self. The self parameter is the instance returned by __new __ (). __init __ () can complete some other initialization actions based on __new __ (), __init__ () Does not require a return value.
__call__: The object is callable. 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.
The __new__ method is not required to be written in the class definition. If it is not defined, it will call object .__ new__ to create an object by default. If it is defined, it will be overridden and use custom, so that you can customize the behavior of creating objects.
Singleton patterns can also be created this way. Click to see [How to create several singleton patterns]
2. For __init__
class Person (object):
def __init __ (self, name, age):
self.name = name
self.age = age
print ('execute__init__')
def __new __ (cls, * args, ** kwargs):
obj = object .__ new __ (cls) # create object
print ('Execute __new__ method')
return obj
p1 = Person ('hc', 24)
print (p1)
Print results:
Execute __new__ method
Execute __init__
<__ main __. Person object at 0x028EB830>
__Init__ method is usually used to initialize a class instance, but __init__ is not the first method to be called when instantiating a class. When an expression such as Persion (name, age) is used to instantiate a class, the first method called is actually the __new__ method. It can be seen from the printed results
If __new __ () does not correctly return an instance of the current class cls, then __init __ () will not be called, even if it is an instance of the parent class.
3. For __call__
Objects can simulate the behavior of functions by providing __call __ (slef, * args, ** kwargs) methods. If an object x provides this method, you can use it like a function, that is, x (arg1, arg2 ... ) Is equivalent to calling x .__ call __ (self, arg1, arg2).
class Foo (object):
def __call __ (self):
pass
f = Foo () #class (), which is the __call__ of the execution metaclass
f () #object (), which is the __call__ of Foo
4, the complete process of instantiating the object
class Foo (Bar):
pass
When we write this code, Python does the following:
有 Is there a metaclass attribute in Foo? If it is, Python will create a class object named Foo in memory through metaclass (I am talking about class objects, please follow my thoughts closely). If Python doesn't Find the metaclass, it will continue to look for the metaclass attribute in Bar (parent class), and try to do the same operation as before. If Python cannot find a metaclass in any parent class, it will look for the metaclass in the module hierarchy and try to do the same. If the metaclass is still not found, Python will use the built-in type to create the class object.
Read the above sentence several times, the question now is, what code can you put in the metaclass?
The answer is: you can create a class of things.
So what can be used to create a class?
Type, or anything that uses type or subclassed type is fine.
Taking the above code as an example, when we instantiate an object obj = Foo (), the __new__ method of the Foo class will be executed first. If it is not written, an object is created using the __new__ method of the parent class and returned Then execute the __init__ method (use your own if you have it, use the parent class if you don't), and initialize the created object.
obj () will execute the __call__ method of the Foo class. Otherwise, the parent class's
We now know that a class is also an object, which is an object of a metaclass. That is, when we instantiate a class, we call its metaclass's __call__ method.
Metaclass processing: When a class is defined, the class is created using a declaration or a default metaclass, the type operation is performed on the metaclass to obtain the parent metaclass (the parent metaclass of the metaclass declared by the class), and the parent meta is called The __call__ function of the class. In the __call__ function of the parent metaclass, call the __new__ 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 metaclass's __init__ initializes the object (here the object refers to the class, because it is an object created by the metaclass), and finally returns the class
1. Object is created by the class. The __init__ method of the class is automatically executed when the object is created. The object () executes the __call__ method of the class.
2. The class is created by type. The __init__ method of type is automatically executed when the class is created. The class () executes the __call__ method of the type (the __new__ method of the class and the __init__ method of the class).
The __call__ of the original type should be the parameter structure and should be:
Metaname, clsname, baseclasses, attrs
__New__ of primitive type
Metaname, clsname, baseclasses, attrs
__Init__ of primitive type
Class_obj, clsname, baseclasses, attrs
The metaclass's __new__ and __init__ affect the behavior of creating class objects. The parent metaclass's __call__ controls the calls to the child metaclass's __new__, __init__, that is, the creation and initialization of class objects. The __new__ and __init__ of the parent metaclass are controlled by the higher level,
In general, the original type is the original parent metaclass, and its __new__ and __init__ are of universal significance, that is, they should be allocated memory, initialized related information, etc.
The metaclass __call__ affects the behavior of creating instances of the class. At this time, if the class customizes __new__ and __init__, you can control the creation and initialization of the object instance
__new__ and __init__ affect the behavior of creating objects. When these functions are in a metaclass, they affect the creation of a class. Similarly, when these two functions are in a common class, they affect the creation of a common object instance. .
__call__ affects () the calling behavior, __call__ is called when the class is created, that is: class Test (object): __metaclass __ = type, the class is created when the class is defined, and the __call__ of the metaclass is called at this time. If the metaclass has Inheritance, when the child metaclass is defined, __call__ of the parent metaclass is executed.
If it is a normal class instantiated object, the __call__ of the normal class is called