Python meta-class
Before thinking clearly to write in the notes, recently saw python3.6 another __init_subclass__
, before the things completely forgotten. This is a summary.
NEW: Combine JavaScript's prototype chain to realize the idea of all objects in a dynamic language.
With a practical example
#!/usr/bin/env pythonclass Type (object): Print ("Run to", "Type") def __init__ (self, type_): Print ("Set Type", Ty Pe_) Self.type_class = Type_ def vaild (self, value): Return isinstance (Value, Self.type_class) class Typec Heckmeta (type): Print ("Run to", "Typecheckmeta") def __new__ (CLS, name, bases, Dict): Print ("Meta-class __new__") Inst = Super (Typecheckmeta, CLS). __new__ (CLS, name, bases, dict) inst._fileds = {} for K, V in Dict.items () : If Isinstance (V, Type): Inst._fileds.setdefault (k, v) return Inst def __init__ (CLS, *args, **kwargs): Print ("Meta class __init__") Super (Typecheckmeta, CLS). __init__ (*args, **kwargs) def __call__ (s Elf, *args, **kwargs): Print ("Meta-class __call__") return super (Typecheckmeta, self). __call__ (*args, **kwargs) class Test (Metaclass=typecheckmeta): Print ("Run to", "Test") name = Type (str), age = Type (int) def __new__ (CLS, *args, **kwargs): Print ("Class __new__") print (args, Kwargs) return super (Test, CLS). __new__ (CLS) def __setattr__ (self, Key, value): Print ("Class __setattr__") if key in Self._fileds:if not Self._fileds[key].vaild (value): Raise TypeError ("Invaild ...") Super (Test, self). __setattr__ (Key, value) def __init__ (Self, a): print ( "Class __init__") def __call__ (self, *args, **kwargs): Print ("class __call__") T = Test (1) print (t)
The scenario is that you need to make a mandatory check on the variables.
Loading process
Commenting out the last two lines of code, you will find the following output
Run to type run to Typecheckmeta run to Testset type <class ' str ' >set type <class ' int ' > class __new__ meta class __init__
First, Python sweeps through the entire file when it loads. When the class definition is encountered, it executes as follows:
- Resolves elements in a class, creates class variables and methods, and loads into class space. The base class information for the class, the meta-class, and so on.
- Locate the class's meta-class, and then call the method of the meta-class, with the
__new__
arguments(类名where,类基类bases,类空间dict)
- The meta-class
__new__
must eventually call the built-in typetype.__new__
type.__new__
is called to __init__
create a class object that is placed in memory. This class object is already loaded.
Execution process
Now let's take a look at the execution
t = Test(1)print(t)
Test
What is it? From a grammatical level, he is a class. However, during execution, after the above loading step, it is a generated instance, so Test()
the method of the meta-class is called __call__
.
- The meta-class must be caught in the
type.__call__
way again.
type.__call__
Method calls the class __new__
method.
- The method of the class
__new__
must fall again intoobject.__new__
object.__new__
Call the method of the class __init__
, and finally an instance is created.
The New method
__init_subclass__(self, k=...)
Trigger time: Triggers when a subclass loads.
Specific: When the child class is loaded, it is found that the parent class defined the __init_subclass__
method, then __new__
__init__
This is called before the meta-class __init_subclass__
. The implementation should not be like this, it should be based on callbacks. For example, detect call __init_subclass__ on the basis of the type meta-element Class).
This allows you to modify subclasses without having to write a meta-class.
There's no magic in the way they pass parameters,
Class Subclass (Father, param= "haha"): Pass
__new__
give now one more positional parameter when passed to
Def __new__ (CLS, name, bases, Dict, **kwargs): Pass
This __init_subclass__
can also be obtained.
Dynamic Language – Everything is an object
function people (name) { this.name = Name}p = new People ("Irn")
Do not understand the JS prototype chain reunion is puzzled by this writing. It is clear function
that the key words indicate that people is a 函数
, so, what is the new 函数
grammar?
In fact, JS function is not only a C-level function, he is a complete instance, is the function created by the instance.
f = new Function(‘name‘, ‘return alert("hello, " + name + "!");‘);
So we have an constructor
object that they can use new
keywords.
When creating an object, the interpreter does the following:
- It creates a new object.
- It sets the constructor property of the object to Vehicle.
- It sets the object to delegate to Vehicle.prototype.
- It calls Vehicle () in the context of the new object.
See the instructions on the web for specific reference!
The class variables and the inheritance of class functions are completed when the prototype is set.
The last call, at which point the this 函数的.prototype.call(第一步创建出来的空对象)
parameter of the function points to the new object, which will have the instance variable (everyone is different)
So the most logical simulation class implementation is this way.
Class Definition/constructorvar Vehicle = function Vehicle (color) { //initialization this.color = color;} Instance Methodsvehicle.prototype = { go:function go () { return "vroom!"; }}
All the variables in the prototype share a copy, which is found in the instance, and the function in this constructor because it points to a {} Every execution will be re-assigned, and will mask the properties set on prototype.
This and prototype are very clever in JS and the whole cornerstone.
Python meta-class