Skip to content

Commit 3e2f326

Browse files
committed
add usage of 'self' and 'super()'
1 parent 1ee1e9f commit 3e2f326

3 files changed

Lines changed: 63 additions & 5 deletions

File tree

chapter/28_python_class_advanced.md

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
1-
<!--
2-
作者:华校专
3-
4-
** 本文档可用于个人学习目的,不得用于商业目的 **
5-
-->
61
# 类的高级主题
72
1.通过在自定义类中嵌入内置类型,类似委托;这样自定义类就可以实现内置类型的接口。
83
这些接口在内部通过操作嵌入的内置类型来实现。
@@ -143,4 +138,67 @@
143138

144139
![多重继承超类定义顺序](../imgs/python_28_12.JPG)
145140

141+
142+
11.类的`.__mro__`属性:类对象的`.__mro__`属性。它是一个`tuple`,里面存放的是类的实例方法名解析时需要查找的类。Python根据该元组中类的前后顺序进行查找。类对象的`.__mro__`列出了`getattr()`函数以及`super()`函数对实例方法名字解析时的类查找顺序。
143+
144+
![类的 __mro__属性](../imgs/python_28_13.JPG)
145+
146+
147+
* 类的`.__mro__`是动态的,当继承层次改变时它也随之改变
148+
* 元类可以重写一个类的`.mro()`方法来定义该类的`__.mro__`属性。该方法在类被创建时调用,结果存放在类的`.__mro__`属性中
149+
150+
12.`super()`函数:`super()`返回一个`super`实例对象,它用于代理实例方法/类方法的执行
151+
152+
* `super(class,an_object)`:要求`isinstance(an_object,class)`为真。代理执行了实例方法调用
153+
* `super(class,class2)`:要求 `issubclass(class2,class)`为真。代理执行了类方法调用
154+
155+
有两种特殊用法:
156+
157+
* `super(class)`:返回一个非绑定的`super`对象
158+
* 在类的实例方法中,直接调用`super()`,等价于`super(classname,self)`(这里`self`可能是`classname`子类实例)
159+
* 在类的类方法中,直接调用`super()`,等价于`super(classname,cls)`(这里`cls`可能是`classname`子类)
160+
161+
原理:`super`的原理类似于:
162+
163+
```
164+
def super(cls,instance):
165+
mro=instance.__class__.__mro__ #通过 instance生成 mro
166+
return mro[mro.index(cls)+1] #查找cls在当前mro中的index,饭后返回cls的下一个元素
167+
```
168+
169+
示例:
170+
171+
```
172+
class Root:
173+
def method1(self):
174+
print("this is Root")
175+
class B(Root):
176+
def method1(self):
177+
print("enter B")
178+
print(self)
179+
super(B,self).method1() #也可以简写为 super().method1()
180+
print("leave B")
181+
class C(Root):
182+
def method1(self):
183+
print("enter C")
184+
print(self)
185+
super().method1() #也可以写成super(C,self).method1()
186+
print("leave C")
187+
class D(B,C):
188+
pass
189+
```
190+
191+
* 调用`D().method1()`--> `D`中没有`method1`
192+
* `B`中找到(查找规则:`D.__mro__`) --> 执行`B`中的`method1`。此时`self`为D实例。`D.__mro__`中,`B`的下一个是`C`,因此`super(B,self).method1()`从类`C`中查找`method1`
193+
* 执行`C``method1`。此时`self`为D实例。`D.__mro__`中,`C`的下一个是`Root`,因此`super(C,self).method1()`从类`Root`中查找`method1`
194+
* 执行`Root``method1`
195+
* `print(self)`可以看到,这里的`self`全部为 `D`的实例
196+
> 类的`classmethod`依次类推
197+
>
198+
> 类、实例的属性查找规则没有那么复杂。因为属性变量只是一个变量,它没办法调用`super(...)`函数。
199+
>只有实例方法和类方法有能力调用`super(...)`函数,才会导致这种规则诞生
200+
201+
![super()和self](../imgs/python_28_14.JPG)
202+
203+
146204

imgs/python_28_13.JPG

19.2 KB
Loading

imgs/python_28_14.JPG

107 KB
Loading

0 commit comments

Comments
 (0)