class A:
sound = '......'
def speak(self): print(self.sound)
class Dog(A):
sound = '汪汪'
dog = Dog()
dog.speak()为什么打印汪汪
这段代码打印出“汪汪”的核心原因在于 Python 的继承机制、self 的动态绑定以及类的属性查找顺序。
我们可以把整个过程拆解为以下 3 个关键点来理解:
1. 继承机制
class Dog(A): 表示 Dog 类继承自 A 类。因此,Dog 类自动拥有了父类 A 的 speak 方法。当你创建 dog = Dog() 并调用 dog.speak() 时,Python 知道要去执行 A 类中定义的 speak 方法。
2. self 到底是谁?(动态绑定)
在 speak(self) 方法中,self 代表的是调用这个方法的实例对象。 因为是 dog.speak(),所以这里的 self 指向的就是 dog 这个实例,而 dog 的类型是 Dog 类。
3. Python 的属性查找顺序(最关键的原因)
当代码执行到 print(self.sound) 时,Python 需要去寻找 sound 这个属性的值。Python 查找属性的顺序是“从下往上,从近到远”:
dog 实例自己有没有 sound 属性(即 dog.__dict__),发现没有。dog 所属的 Dog 类中寻找,发现 Dog 类里定义了 sound = '汪汪'。查找成功,立刻停止,并使用这个值。Dog 类里没有定义 sound,Python 才会继续去父类 A 中寻找,那时才会找到 '......'。