BrightXiong 发表于 2023-3-21 22:39:48

类和对象-Ⅳ

>>> # 在类中定义 __init__() 方法,可以实现在实例化对象的时候进行个性化定制:
>>> class C:
...         def __init__(self, x, y):
...                 self.x = x
...                 self.y = y
...         def add(self):
...                 return self.x + self.y
...         def mul(self):
...                 return self.x * self.y
...
>>> c = C(2, 3)
>>> c.add()
5
>>> c.mul()
6
>>> # 如果对于父类的某个属性或方法不满意的话,完全可以重新写一个同名的属性或方法对其进行覆盖。那么这种行为,我们就称之为是子类对父类的重写。
>>> class D(C):
...         def __init__(self, x, y, z):
...                 self.z = z
...                 C.__init__(self, x, y)
...         def add(self):
...                 return C.add(self) + self.z
...         def mul(self):
...                 return C.mul(self) * self.z
...
>>> d = D(2, 3, 4)
>>> d.add()
9
>>> d.mul()
24

>>> # 定义一个新的类 —— D,继承自上面的类 C,然后对 add() 和 mul() 方法进行重写:
>>> # 类 B1 和 类 B2 都是继承自同一个父类 A,而类 C 又同时继承自它们,这种继承模式就被称之为钻石继承,或者菱形继承:
>>> class B1(A):
...         def __init__(self):
...                 A.__init__(self)
...                 print("哈罗,我是B1")
...
>>> class B2(A):
...         def __init__(self):
...                 A.__init__(self)
...                 print("哈罗,我是B2")
...
>>> class C(B1, B2):
...         def __init__(self):
...                 B1.__init__(self)
...                 B2.__init__(self)
...                 print("哈罗,我是C~~")
...
>>> c = C()
哈罗,我是A
哈罗,我是B1
哈罗,我是A
哈罗,我是B2
哈罗,我是C~~
>>> # 看,“哈喽,我是A~” 这一句竟然打印了 2 次!
>>> # 类 A 的构造函数被调用了 2 次!
>>> # 上面这种通过类名直接访问的做法,是有一个名字的,叫 “调用未绑定的父类方法”。
>>> # 通常使用其实没有多大问题,但是遇到钻石继承嘛,就容易出事儿了~

>>> # super() 函数能够在父类中搜索指定的方法,并自动绑定好 self 参数。
>>> class B1(A):
...         def __init__(self):
...                 super().__init__()
...                 print("哈罗,我是B1")
...
>>> class B2(A):
...         def __init__(self):
...                 super().__init__()
...                 print("哈罗,我是B2")
...
>>> class C(B1, B2):
...         def __init__(self):
...                 super().__init__()
...                 print("哈罗,我是C~~")
...
>>> c = C()
哈罗,我是A
哈罗,我是B2
哈罗,我是B1
哈罗,我是C~~
>>> # 之所以 super() 函数能够有效避免钻石继承带来的问题,是因为它是按照 MRO 顺序去搜索方法,并且自动避免重复调用的问题
>>> # MRO(Method Resolution Order),翻译过来就是 “方法解析顺序”。

>>> # 想要查找一个类的 MRO 顺序有两种方法
>>> # 一种是通过调用类的 mro() 方法:
>>> C.mro()
[<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.B2'>, <class '__main__.A'>, <class 'object'>]
>>> # 另一种则是通过 __mro__ 属性
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.B2'>, <class '__main__.A'>, <class 'object'>)
>>> # 注:这里大家会看到它们都有一个 <class 'object'>,这是因为 object 是所有类的基类,所以就算你不写,它也是会被隐式地继承
>>> B1.mro()
[<class '__main__.B1'>, <class '__main__.A'>, <class 'object'>]
>>> B1.__mro__
(<class '__main__.B1'>, <class '__main__.A'>, <class 'object'>)
>>>
页: [1]
查看完整版本: 类和对象-Ⅳ