python super()双参数版本的上下文__

2024-04-20 07:09:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经读了the documentation for ^{}多次,但我仍然不知道两个参数版本返回的结果。在

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class.

  1. 什么是代理对象?在
  2. 父母或兄弟姐妹?在

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 (this is useful for classmethods).

  1. 这一切都很好,但是返回的是什么?语法super(a,b)是什么意思?在

^{}的上下文中

Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super(currentclass, cls).__new__(cls[, ...]) with appropriate arguments and then modifying the newly-created instance as necessary before returning it.

super(currentclass, cls).__new__(cls[, ...])

如果currentclass等于cls,则有{}

  1. 那会有什么回报?这个语法是什么意思?在
  2. 此语句如何返回cls的实例,以便在返回的对象上调用__init__?在

Tags: ofthe对象newforthatobjectis
2条回答

你应该看一下雷蒙德·海丁格的《2015年PyCon》的演讲,Super is considered super!

但如果没有,为什么不加上一堆打印声明来回答你的问题呢?在

# (object) is only required in Python2
class Mom(object):
    def __init__(self, *args, **kwargs):
        print('Mom is initializing - args: {!r} kwargs: {!r}'.format(
              args, kwargs))

    def do_something(self):
        print('Doing some Mom thing')


class Dad(object):
    def __init__(self, *args, **kwargs):
        print('Dad is initializing - args: {!r} kwargs: {!r}'.format(
              args, kwargs))

    def do_something(self):
        print('Doing some Dad thing')


class Sister(Mom, Dad):
    def __init__(self, name):
        print('initializing a Sister with name: {!r}'.format(name))
        parent = super(Sister, self)
        print(type(parent))
        print(parent)
        print('Calling super __init__')
        parent.__init__(name)

    def do_something(self, value):
        if value == 5:
            print('calling method on super')
            super(Sister, self).do_something()
        else:
            print('Sister did something')


class Brother(Mom):
    def __init__(self, name):
        print('initializing a Brother with name: {!r}'.format(name))
        parent = super(Brother, self)
        print(type(parent))
        print(parent)
        print('Calling super __init__')
        parent.__init__(name)

    def do_something(self, value):
        if value == 5:
            print('calling method on super')
            super(Brother, self).do_something()
        else:
            print('Brother did something')


b = Brother('Bear')
s = Sister('Moon')

b.do_something(3)
b.do_something(5)

s.do_something(3)
s.do_something(5)

产生以下输出(附加注释):

^{pr2}$

显然,super返回super类型的类。根据文档,它是一个代理对象。根据定义,代理是对其他事物的替代。在本例中,代理是获取Mom的替代品。您可以看到,当我们实际调用__init__函数时,Mom的init函数被调用。在

initializing a Sister with name: 'Moon'
<type 'super'>
<super: <class 'Sister'>, <Sister object>>
Calling super __init__
Mom is initializing - args: ('Moon',) kwargs: {}

您会注意到,Dad的init函数没有被调用。这是因为,如果你看Raymond的演讲,你就会知道super从左到右寻找父函数。在

Brother did something
calling method on super
Doing some Mom thing

你在这里看到同样的行为

Sister did something
calling method on super
Doing some Mom thing

如果你改变顺序,你会看到的:

initializing a Brother with name: 'Bear'
<type 'super'>
<super: <class 'Brother'>, <Brother object>>
Calling super __init__
Mom is initializing - args: ('Bear',) kwargs: {}
initializing a Sister with name: 'Moon'
<type 'super'>
<super: <class 'Sister'>, <Sister object>>
Calling super __init__
Dad is initializing - args: ('Moon',) kwargs: {}
Brother did something
calling method on super
Doing some Mom thing
Sister did something
calling method on super
Doing some Dad thing

总而言之:

  1. 代理是代表其他事物的东西。在我们的例子中,super是妈妈和爸爸的代理,这取决于它们继承的顺序。

  2. 老实说,我找不到任何有意义的兄弟姐妹。我不知道你什么时候需要。

  3. 返回super的实例。

  4. 只有当你有从type继承的东西,例如super(type, type)时,这才真正有效,因为你需要一个该类型的实例object也可以工作,因为:

    打印(isinstance(object,object)) 打印(isinstance(type,type)) 打印(isinstance(对象,类型)) 打印(isinstance(type,object))

在这个过程中,有一些非常复杂的魔法。在

  1. 你在问函数如何返回东西吗?因为new是一个函数,它返回或不返回。object.__new__返回一些东西。我不确定该函数的实际源代码在哪里,或者如果您对确切的机制感兴趣,我可以告诉您。在

“what does superreturn”的答案与“it return a list”或“it return a modified copy of The second object”不同。super返回一个类型为super的对象,该类型专门设计为具有文档所述的质量。在

也许这将有助于展示super的纯Python实现。如果super不是用C编写的,它基本上如下所示:

class super(object):
    def __init__(self, klass, object_or_klass):
        # The real super can be called with 0 arguments on Python 3,
        # but digging into the magic that makes that work isn't relevant here.

        if isinstance(object_or_klass, klass):
            mro = type(object_or_klass).__mro__
            self.obj_type = type(object_or_klass)
            self.obj = object_or_klass
        elif issubclass(object_or_klass, klass):
            mro = object_or_klass.__mro__
            self.obj_type = object_or_klass
            self.obj = None
        else:
            raise TypeError

        # Set up a copy of the MRO to search,
        # with everything up to and including klass skipped
        self.searchlist = mro[mro.index(klass)+1:]

    def __getattribute__(self, name):
        # self.searchlist would be infinite recursion, as would super().__getattribute__
        searchlist = object.__getattribute__(self, 'searchlist')

        # Search the method resolution order for the attribute we want.
        for klass in searchlist:
            if name in klass.__dict__:
                attr = klass.__dict__[name]
                break
        else:
            raise AttributeError

        if hasattr(attr, '__get__'):
            # Handle descriptors.
            obj = object.__getattribute__(self, 'obj')
            obj_type = object.__getattribute__(self, 'obj_type')
            attr = attr.__get__(obj, obj_type)
        return attr

现在您可以看到super(a, b)构造了一个super对象,而super(a, b).whatever调用了super对象的__getattribute__方法来搜索第二个参数的方法解析顺序,以找到我们想要的属性。b.whatever的属性查找过程非常相似,只是没有切掉MRO的第一部分,如果{}不是类,则检查实例dict。在

相关问题 更多 >