super()返回的超级对象的类型是什么?

Tim*_*Tim 6 python python-3.x

这里:

super( [ type [ , object-or-type ]] )
Run Code Online (Sandbox Code Playgroud)

返回一个代理对象,该方法将方法调用委托给父类或兄弟类type.这对于访问已在类中重写的继承方法很有用.搜索顺序与使用的搜索顺序相同,getattr()只是type跳过了自身.

如果省略第二个参数,则返回的超级对象是未绑定的.

如果第二个参数是一个对象,则isinstance(obj, type)必须为true.

如果第二个参数是一个类型,则issubclass(type2, type)必须为true(这对于classmethods很有用).

  1. 如果我是正确的,则类型是类,类是类型.类是一个对象,因此类型也是一个对象.当第二个参数是一个类型的对象时,为什么引用会区分这两种情况?

  2. 当第二个参数是一个类型时,为什么issubclass(type2, type) 要求为真?

  3. super分别在三种情况下返回的超级对象的类型是什么?或者你如何确定返回的超级对象的类型super

    当第二个参数是一个对象时,因为"搜索顺序与getattr()除了type自身被跳过之外的搜索顺序相同",我猜测super函数返回的superobject的类型应该是第一个参数的任何祖先类的子类type,但我发现它实际上不是通过测试issubclass.所以我误解了什么?

Mar*_*ers 5

您似乎将这个词typetype()内置词混淆了。在这里,他们只是引用传入的第一个参数super()

文档告诉你的是,如果你传入两个参数,那么第二个参数要么必须是第一个参数的实例,要么必须是一个子类。换句话说,要么isinstance(first_argument, second_argument)issubclass(first_argument, second_argument)必须为真。这里没有其他含义

就像int()orstr()或任何其他内置类型一样,调用返回的对象的类型super() 就是 type。没有为不同的参数返回单独的类型。请参阅定义对象C 源代码

super()对象实现了一个__getattribute__钩子,该钩子实现了特定的属性行为。该文件告诉你的是,规则的属性查找是一样的getattr()(但与记录MRO跳过),但这并不意味着super()收益的祖先类。

实际发生的是,super().__getattribute__采用第二个参数的MRO(无论是type(instance).__mro__cls.__mro__,取决于羯羊isinstance()issubclass()为真),发现该序列的第一个参数,并开始测试了之后的属性。因为首先扫描 MRO 以查找第二个参数的(类型),所以它必须是可找到的,这就是为什么约束是它们的原因。

在纯 Python 中,这就是这样super()做的(简化为仅关注两个参数行为):

def _supercheck(type_, obj):
    try:
        if issubclass(obj, type_):
            return obj
    except TypeError:
        # obj is not a type so issubclass throws a TypeError
        pass
    if isinstance(obj, type_):
        return type(obj)
    raise TypeError(
        "super(type, obj): obj must be an instance or subtype of type")


class super_:
    def __init__(self, type_, obj):
        # simplified for the two-argument case
        self.type_ = type_
        self.obj = obj
        self.obj_type = _supercheck(type_, obj)

    def __getattribute__(self, name):
        if name == '__class__':
            # __class__ should always come from this object, not
            # the represented MRO.
            return super().__getattribute__(name)

        # avoid infinite recursion issues
        sd = super().__getattribute__('__dict__')
        starttype = sd['obj_type']
        type_ = sd['type_']
        obj = sd['obj']

        mro = iter(starttype.__mro__)

        # skip past the start type in the MRO
        for tp in mro:
            if tp == type_:
                break

        # Search for the attribute on the remainder of the MRO
        for tp in mro:
            attrs = vars(tp)
            if name in attrs:
                res = attrs[name]
                # if it is a descriptor object, bind it
                descr = getattr(type(res), '__get__', None)
                if descr is not None:
                    res = descr(
                        res,
                        None if obj is starttype else obj,
                        starttype)
                return res

        return super().__getattribute__(name)
Run Code Online (Sandbox Code Playgroud)