0

合作方式及超级

super这是Guido内置的纯 Python 实现示例,用于说明目的。Super我需要对以下类的实现进行一些说明

在下面的代码中调用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__'
4

2 回答 2

6

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

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

尽管删除的文本在其对旧式对象的描述中是正确的,但在查看了完整的代码和异常之后,这不是导致该异常的问题。上面的异常是内置super捕获下面确定的错误:Dis not a subclass of 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__)

假设 if__obj__不是 的实例__type__,则__obj__它本身就是一个类型,并且它有一个 mro。如果您提供的类型不是 的基类(或类),则没有处理程序__obj__,因为super(或Super)无法明智地处理它。

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

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

于 2013-09-05T15:25:49.160 回答
0

我现在明白了。Builtinsuper可以这样调用:super(type, type2)它要求 type2 是 type 的子类。在Super这样调用的实现中,Super(type, type2) isinstance(type2, type)将导致对type2 的mro进行评估。所以基本上 Super 正在尝试与内置功能保持一致

于 2013-09-06T05:58:52.167 回答