1. 重载运算符的调用顺序
class Foo:
def __init__(self, name):
self._name = name
def __str__(self):
return self._name
def __eq__(self, other):
return other is self
class Bar(Foo):
def __eq__(self, other):
return str(self) == str(other)
class Foo1:
def __init__(self, name):
self._name = name
def __str__(self):
return self._name
def __eq__(self, other):
return str(self) == str(other)
foo = Foo("Hello")
bar = Bar("Hello")
foo1 = Foo1("Hello")
print(foo == bar) # True, 调用了 bar 的 __eq__
print(bar == foo) # True, 调用了 bar 的 __eq__
print(foo == foo1) # False, 调用了 foo 的 __eq__
print(foo1 == foo) # True, 调用了 foo1 的 __eq__
Python 中,如果 ==
符号两端变量属于具有继承关系的类,则会优先调用子类的重载方法;如果 ==
符号两端变量分别属于两个完全不同的类,则会调用左端类的重载进行判断(见代码中print
部分的后两个)
如果一个没有重载,一个有重载,则会优先调用有重载的类的重载方法。
2. 多继承类的 MRO (Method Resolution Order)
class GrandParent:
def __init__(self):
print("Grandparent")
class Parent(GrandParent):
def __init__(self):
print("parent")
class Son(Parent, GrandParent): # 反过来会报错
def __init__(self):
super().__init__()
print("son")
a = Son()
# parent
# son
参考文章:https://www.educative.io/edpresso/what-is-mro-in-python
这个参考文章比较详细,但是讲的有点复杂了。简单来说就是 CPython 在解析多个类继承的时候,会在继承的类里从左到右进行 DFS 查找,直到找到对应的方法为止。
3. 装饰器的调用顺序
print(10.1)
def func1(function):
print(11.1)
def func1_inter():
print(11.2, func1_inter)
function() # func2_inter
print(11.4)
function() # func2_inter
print(11.5)
print(11.6)
return func1_inter
def func2(function):
print(12.1)
def func2_inter():
print(12.2, func2_inter)
function() # my_func
print(12.3)
function() # my_func
print(12.5)
print(12.6)
return func2_inter
print(10.2)
@func1
@func2
def my_func():
print(10.3)
print(10.4)
my_func()
print(10.5)
这个例子比较全面地展示了 Python 装饰器之间的调用关系。