- Basic concepts: Multiple inheritance - Liao Xuefeng
Sequence problem & homonymy method
Question: if there are methods with the same name in different parent classes, which parent class method will be called by the subclass object when calling the method?
MRO in Python (method search order)
- Python provides a built-in property mro for classes to view the method search order
- MRO is a method resolution order, which is mainly used to judge the call path of methods and properties during multi inheritance
- print(C.__mro__) #C is the class name after multi inheritance
- reference resources: Detailed explanation of Python multi inheritance and super use
When a subclass derives from more than one parent class and the subclass does not have its own constructor:
- Inherit in order. Which parent class is the first and has its own constructor will inherit its constructor;
- If the first parent class does not have a constructor, it inherits the constructor of the second one. If the second one does not, look back, and so on.
super() and calling parent class methods:
- super().__init__ Compared with the class name. Init, the usage of single inheritance is basically the same; However, in multi inheritance, the super method can ensure that the method of each parent class will be executed only once, and the method using the class name will cause the method to be executed multiple times.
- For multiple inheritance, if there are multiple constructors to call, we must use the traditional method: parent class__ init__(self)
Class magic method (class__ fun__())
This is due to the "duck type" of dynamic language, which does not need to forcibly inherit an interface.
- Initialization / instantiation:__ init__
- len(): __len__
- with: __enter__ And__ exit__
- Limit sample properties:__ slots__: The defined properties only work on the current class instance and have no effect on the inherited subclasses.
- str() / print(): __str__
- During commissioning:__ repr__
- Returns an iteration object, for...in:__ iter__
- next() gets the next value of the generator:__ next__
- Access the list by subscript or dictionary key a:__ getitem__
- Assign a value to a set by treating the object as a list or dict:__ setitem__
- Delete element del xxx:__ delitem__
- getattr(): __getattr__
- Called only if the property is not found__ getattr__， Existing attributes, such as name, will not be__ getattr__ Find in.
- Implement chain call
- Call:__ call__
- When we call the instance method, we do not need to call instance.method(), but directly call it on the instance itself.
- Through callable(): judge whether an object is a "callable" object.
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) >>> s = Student('Michael') >>> s() # Do not pass in the self parameter My name is Michael.
- reference resources: Custom class - Liao Xuefeng
- Essence: the decorator is actually a function because:
- Argument is a function
- The return value is also a function
from functools import wraps def my_log(fun): @wraps(func) def wrapper(self, *args, **kwargs): print('hello world') print(self) # Get the instance of the original function and call some methods of the corresponding instance return func(*args, **kwargs) # The original function may have a return value return wrapper @my_log # Equivalent to run = my_log(run), i.e. run = wrapper. def run(): print('run') @my_log def add(a, b): print(u'The result is:%s' % (a+b)) run() # run.__name__ Represents the name of the run function print(run.__name__) add(1, 2)
# With parameters def my_log(param): def decorator(fun): @wraps(func) def wrapper(self, *args, **kwargs): print(param) print('hello world') print(self) # Get the instance of the original function and call some methods of the corresponding instance return func(*args, **kwargs) # The original function may have a return value return wrapper return decorator @my_log("parameter") # It is equivalent to add = decorator, that is, add = decorator(add), that is, add = wrapper????????? def add(a, b): print(u'The result is:%s' % (a+b)) add(1, 2)
- The decorator uses the @ symbol before the function.
- *args, **kwargs: the location is passed to participate in the keyword, and the passed parameters can be combined to represent any parameter. Solve the problem of parameter uncertainty when transmitting parameters.
- @wraps(func) ensures that functions are related__ name__ And other private properties are not lost.
- Get the instance of the original function through self, so as to call some methods of the corresponding instance
class logit(object): def __init__(self, logfile='out.log'): self.logfile = logfile def __call__(self, func): @wraps(func) def wrapped_function(self_func, *args, **kwargs): print("Decorator!!!") print(self_func) # Get the instance of the original function and call some methods of the corresponding instance self.notify() # Class method return func(*args, **kwargs) return wrapped_function def notify(self): # logit only logs, nothing else pass @logit() # Can pass parameters def myfunc1(): pass