关于python super():python super() – __new__上下文中的两个参数版本

python super() - two argument version in context of __new__

本问题已经有最佳答案,请猛点这里访问。

我已经多次阅读了super()的文档,但我仍然不知道这两个参数版本返回的是什么。

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.

  • 什么是代理对象?
  • 父母还是兄弟姐妹?
  • 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).

  • 很好,但是还回来了什么?语法super(a,b)是什么意思?
  • __new__中,

    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.

    埃多克斯1〔3〕

    如果currentclass等于cls,则为super(currentclass, currentclass)

  • 那又是什么呢?那个语法是什么意思?
  • 该语句如何返回cls的一个实例,以便对返回的对象调用__init__

  • "super返回什么"的答案与"它返回一个列表"或"它返回第二个对象的修改副本"不同。super返回super类型的对象,该类型专门设计为具有文档所说的质量。

    也许这将有助于显示super的纯Python实现。如果super不是用C写的,基本上是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    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,如果b不是类。


    你一定要看雷蒙德·赫廷格在2015年的Pycon演讲,超级被认为是超级的!

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    # (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)

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

    1
    2
    3
    4
    <type 'super'>
    <super: <class 'Brother'>, <Brother object>>
    Calling super __init__
    Mom is initializing - args: ('Bear',) kwargs: {}

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

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

    您会注意到,这里没有调用dad的init函数。这是因为,如果你看雷蒙德的演讲,你会知道super从左到右寻找父母的功能。

    1
    2
    3
    Brother did something
    calling method on super
    Doing some Mom thing

    你看到同样的行为在这里重复

    1
    2
    3
    Sister did something
    calling method on super
    Doing some Mom thing

    如果您将Sister的订单更改为Dad, Mom,您将看到这些调用会发生更改:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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

    总结如下:

  • 代理是代表其他事物的东西。在我们的例子中,super是父母双方的代理,这取决于他们继承的顺序。

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

  • 返回super的一个实例。

  • 只有当你有从type继承的东西,例如super(type, type),这才真正有效,因为你需要这种类型的实例。object也会起作用,因为:

    打印(IsInstance(Object,Object))打印(IsInstance(Type,Type))打印(IsInstance(Object,Type))打印(IsInstance(Type,Object))

  • 在这个过程中有一些相当复杂的魔法。

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