2021.09.05 - Summary of key and difficult points of Python

Posted by GateGuardian on Sun, 05 Sep 2021 20:31:07 +0200

multiple inheritance

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[1]:__ 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.

Detailed decorator

  • Essence: the decorator is actually a function because:
    • Argument is a function
    • The return value is also a function

Function decorator

No parameters

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

# 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 decorator

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

Topics: Python