Posted in Python onApril 23, 2015
子类里访问父类的同名属性,而又不想直接引用父类的名字,因为说不定什么时候会去修改它,所以数据还是只保留一份的好。其实呢,还有更好的理由不去直接引用父类的名字,参见 Python's super() considered super! | Deep Thoughts by Raymond Hettinger。
这时候就该 super() 登场啦——
class A: def m(self): print('A') class B(A): def m(self): print('B') super().m() B().m()
当然 Python 2 里 super() 是一定要参数的,所以得这么写:
class B(A): def m(self): print('B') super(B, self).m()
需要提到自己的名字。这个名字也是动态查找的,在这种情况下替换第三方库中的类会出问题。
super() 很好地解决了访问父类中的方法的问题。那么,如果要访问父类的父类(准确地说,是方法解析顺序(MRO)中位于第三的类)的属性呢?
比如,B 类是继承 A 的,它重写了 A 的 m 方法。现在我们需要一个 C 类,它需要 B 类的一些方法,但是不要 B 的 m 方法,而改用 A 的。怎么间接地引用到 A 的 m 方法呢?使用self.__class__肯定是不行的,因为 C 还可能被进一步继承。
从文档中我注意到,super 的实现是通过插入一个名为 __class__ 的名字来实现的(super 会从调用栈里去查找这个 __class__ 名字)。所以,就像文档里暗示的,其实可以直接在定义方法时访问 __class__ 名字,它总是该方法被定义的类。继续我们的单字母类:
class C(B): def m(self): print('C') # see the difference! print(__class__.__mro__) print(self.__class__.__mro__) __class__.__mro__[2].m(self) class D(C): def m(self): print('D') super().m() o = D() o.m()
会得到:
D C (<class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>) (<class 't.D'>, <class 't.C'>, <class 't.B'>, <class 't.A'>, <class 'object'>) A
不过,PyPy 并不支持这个 __class__ 名字。
Python3里的super()和__class__使用介绍
- Author -
依云声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@