super(type, self)与super(type1, type2)的区别
发布日期:2021-06-29 16:00:27 浏览次数:2 分类:技术文章

本文共 3755 字,大约阅读时间需要 12 分钟。

好的,我最近通过一些实验发现,我的理解有一些问题。在此之前我们先关心一下python文档中是怎么描述super

  • super(type[, object-or-type])
    Return the superclass of type. If the second argument is omitted the super object returned is unbound. If the second argument is an object, isinstance(obj, type) must be true. If the second argument is a type, issubclass(type2, type) must be true. super() only works for new-style classes.

我之所以说我们之前 文章中还有一些问题没有解决,也是因为文档的第一句话返回一个superclass类型,但是我们这样测试的时候出现了问题

c = C()super(C, c) == AOut[18]: False

这就让我很困惑了,文档中的第一句描述是不对的。这其实很好理解

A.__mro__Out[19]: (__main__.A, __main__.Base, object)C.__mro__Out[20]: (__main__.C, __main__.A, __main__.B, __main__.Base, object)

因为Amro表中不包含B。好的,我们处理了第一个问题。

我现在要提到的是两个新的概念boundunbound,看这样的一个例子

class Base:    def __init__(self, name):        self.name = name    def func(self):        print('name ', self.name)a = Base('a')

我们这样去做(python2.7下)

>>> a.func
>>>> Base.func

而在python3.6

>>> a.funcOut[35]: 
>>>> Base.funcTraceback (most recent call last): File "
", line 1, in
Base.funcAttributeError: type object 'Base' has no attribute 'func'

我们暂时不讨论这个变化,我们先在python2.7下看问题。字面上很容易理解bound就是绑定,我们通过实例去调用类的方法实际上是这样做的Base.__dict__['func'].__get__(a, Base),很容易验证

>>> Base.__dict__['func'].__get__(a, Base) == a.funcTrue

而对于unbound操作来说

>>> Base.__dict__['func'].__get__(None, Base) == Base.funcTrue

你应该注意到了boundunbound的区别,就是__get__操作的第一个参数是不是传入了一个实例对象。

我们将上述的过程放到python3.6下同样也是成立的,以下是验证。

Base.__dict__['func'].__get__(a, Base) == a.funcOut[46]: TrueBase.__dict__['func'].__get__(None, Base) == Base.funcOut[47]: True

我们继续回到super的话题,我们这里给出super是什么。它是一个代理对象,用来访问MRO表中的方法。

我们在python2.7下回答上一篇文章中没有提到的问题,super(C, C)super(C, c)有什么关系

>>> super(C, C)
,
>>>> super(C, c)
,
>>>> super(C, C).__init__ == A.__init__True>>> super(C, c).__init__ == A.__init__False>>> super(C, C) == super(C, c)False

我们发现这里出现一个然我们很困惑的东西,为什么super(C, C)super(C, c)既相同又不相同?我想这应该是一个bug。我们到python3.6下验证

super(C, C)Out[89]: 
super(C, c)Out[90]:
>super(C, C).__init__ == A.__init__Out[91]: Truesuper(C, c).__init__ == A.__init__Out[92]: False

那么现在我们就应该猜到了super(C, C).__init__super(C, c).__init__的区别,也就是一个unbound一个bound。很容易验证(python 3.6

super(C, C).__init__Out[108]: 
super(C, c).__init__Out[109]:
>

但是在python 2.7下又出现了这样

>>> super(C, C).__init__
>>> super(C, c).__init__
>

原因可以看这篇

那么是否可以这样去做super(C, C).__dict__['__init__'].__get__(None, A),并不可以,这样做是错的!!!

>>> super(C, C).__dict__['__init__'].__get__(None, A)Traceback (most recent call last):  File "
", line 1, in
super(C, C).__dict__['__init__'].__get__(None, A)TypeError: 'getset_descriptor' object is not subscriptable

究其原因,其实就像本文的一开头

super(C, C) == AOut[101]: Falsesuper(C, c) == AOut[102]: False

原因我也说了,super返回的是一个代理对象,自然和对象本身不同。

貌似没什么问题了,但是,,,

python2.7>>> print super.__doc__super(type, obj) -> bound super object; requires isinstance(obj, type)super(type) -> unbound super objectsuper(type, type2) -> bound super object; requires issubclass(type2, type)Typical use to call a cooperative superclass method:class C(B):    def meth(self, arg):        super(C, self).meth(arg)python3.6>>> print(super.__doc__)super() -> same as super(__class__, 
)super(type) -> unbound super objectsuper(type, obj) -> bound super object; requires isinstance(obj, type)super(type, type2) -> bound super object; requires issubclass(type2, type)Typical use to call a cooperative superclass method:class C(B): def meth(self, arg): super().meth(arg)This works for class methods too:class C(B): @classmethod def cmeth(cls, arg): super().cmeth(arg)

你也看到了super(type, type2)是一个bound,QAQ。看这篇

转载地址:https://coordinate.blog.csdn.net/article/details/79508630 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python描述符使用指南
下一篇:python super中的mro表

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月21日 11时32分53秒