|
1 | | -<!-- |
2 | | - 作者:华校专 |
3 | | - |
4 | | -** 本文档可用于个人学习目的,不得用于商业目的 ** |
5 | | ---> |
6 | 1 | # 类的高级主题 |
7 | 2 | 1.通过在自定义类中嵌入内置类型,类似委托;这样自定义类就可以实现内置类型的接口。 |
8 | 3 | 这些接口在内部通过操作嵌入的内置类型来实现。 |
|
143 | 138 |
|
144 | 139 |  |
145 | 140 |
|
| 141 | + |
| 142 | +11.类的`.__mro__`属性:类对象的`.__mro__`属性。它是一个`tuple`,里面存放的是类的实例方法名解析时需要查找的类。Python根据该元组中类的前后顺序进行查找。类对象的`.__mro__`列出了`getattr()`函数以及`super()`函数对实例方法名字解析时的类查找顺序。 |
| 143 | + |
| 144 | +  |
| 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 | +  |
| 202 | + |
| 203 | + |
146 | 204 |
|
0 commit comments