首页 文章

什么's wrong with Guido'在Python中实现Super?

提问于
浏览
0

Cooperative methods and super

This is an example pure python implementation of built in super by Guido for illustration purposes. I need some clarification on implementation of class Super below

在下面的代码调用 someobj.__mro__ 将无法正常工作 . 看到我对这条线的评论 . 内置 super 只会引发错误 .

TypeError: super(type, obj): obj must be an instance or subtype of type

题:

我的问题是,首先要有这条线的意图是什么?

因此,如果传入的对象不是传入类的实例,那么开始使用对象的mro ...为什么?

class Super(object):
        def __init__(self, type, obj=None):
            self.__type__ = type
            self.__obj__ = obj
        def __get__(self, obj, type=None):
            if self.__obj__ is None and obj is not None:
                return Super(self.__type__, obj)
            else:
                return self
        def __getattr__(self, attr):
            if isinstance(self.__obj__, self.__type__):
                starttype = self.__obj__.__class__
            else:
                starttype = self.__obj__   ## This line does not work
            mro = iter(starttype.__mro__)
            for cls in mro:
                if cls is self.__type__:
                    break
            # Note: mro is an iterator, so the second loop
            # picks up where the first one left off!
            for cls in mro:
                if attr in cls.__dict__:
                    x = cls.__dict__[attr]
                    if hasattr(x, "__get__"):
                        x = x.__get__(self.__obj__)
                    return x
            raise AttributeError, attr

class A(object):
        def m(self):
            '''  m in A'''
            return "A"

class B(A):
        def m(self):
            '''  m in B'''
            return "B" + Super(B, self).m()

class C(A):
        def m(self):
            ''' m in C '''
            return "C" + Super(C, self).m()

class D(C):
        def m(self):
            ''' m in D'''
            return "D" + Super(B, self).m()

print D().m() # "DCBA"

堆栈跟踪:

Traceback (most recent call last):
  File "./supertest.py", line 73, in <module>
    print D().m() # "DCBA"
  File "./supertest.py", line 71, in m
    return "D" + Super(B, self).m()
  File "./supertest.py", line 33, in __getattr__
    mro = iter(starttype.__mro__)
AttributeError: 'D' object has no attribute '__mro__'

2 回答

  • 6

    TypeError:super(type,obj):obj必须是类型的实例或子类型

    您作为obj传递的对象是旧式对象(旧式类的实例) . 这些都具有classobj类型,不是object的子类,也不是type类型(或类型的子类) .

    虽然在描述完旧代码和异常时,删除文本在旧样式对象的描述中是正确的,但这不是导致该异常的问题 . 上面的异常是内置 super 捕获下面指出的错误: D 不是 B 的子类,所以 super 告诉你它不能对这对输入做任何事情 .

    我的问题是首先拥有这条线的意图是什么?

    触发回溯的问题(完整的回溯,而不是上面讨论的第一个错误)是 D 不是 B 的子类 .

    在这段代码中:

    if isinstance(self.__obj__, self.__type__):
        starttype = self.__obj__.__class__
    else:
        starttype = self.__obj__   ## This line does not work
    mro = iter(starttype.__mro__)
    

    假设如果 __obj__ 不是 __type__ 的实例,那么 __obj__ 本身就是一个类型,并且它有一个mro . 对于你提供的类型不是 __obj__ 的基类(或类)的情况,没有处理程序,因为 super (或 Super )没有任何理由可以使用它 .

    这里唯一的设计缺陷是构造函数应该捕获这种情况,并生成一个适当的异常 .

    最后,我注意到您发布的代码与您链接的文档中的代码不同 . Guido的代码实际上并没有触发这个问题 .

  • 0

    我现在明白了 . 可以这样调用Builtin supersuper(type, type2) ,这要求type2是类型的子类 . 在 Super 实现中,当被调用时, Super(type, type2) isinstance(type2, type) 将失败,导致被评估的type2的 mro . 所以基本上Super正在尝试与内置功能进行功能奇偶校验

相关问题