使用 super 的正确方法(参数传递) [英] correct way to use super (argument passing)

查看:95
本文介绍了使用 super 的正确方法(参数传递)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我关注了Python 的超级被认为有害,并去测试他的例子.>

但是,示例 1-3,它应该显示正确的在处理需要不同参数的 __init__ 方法时调用 super 的方式,完全无效.

这是我得到的:

~ $ python example1-3.pyMRO: ['E', 'C', 'A', 'D', 'B', 'object']E arg = 10参数 = 10一种D arg = 10乙回溯(最近一次调用最后一次):文件下载/example1-3.py",第 27 行,在 <module> 中E(参数=10)文件下载/example1-3.py",第 24 行,在 __init__ 中super(E, self).__init__(arg, *args, **kwargs)文件下载/example1-3.py",第 14 行,在 __init__ 中super(C, self).__init__(arg, *args, **kwargs)文件下载/example1-3.py",第 4 行,在 __init__ 中super(A, self).__init__(*args, **kwargs)文件下载/example1-3.py",第 19 行,在 __init__ 中super(D, self).__init__(arg, *args, **kwargs)文件下载/example1-3.py",第 9 行,在 __init__ 中super(B, self).__init__(*args, **kwargs)类型错误:object.__init__() 不带参数

似乎object 本身违反了文档中提到的最佳实践之一,即使用super 的方法必须接受*args**kwargs.

现在,奈特先生显然希望他的示例能够工作,那么最近版本的 Python 是否对此有所更改?我检查了 2.6 和 2.7,都失败了.

那么处理这个问题的正确方法是什么?

解决方案

有时两个类可能有一些共同的参数名称.在这种情况下,您不能从 **kwargs 中弹出键值对或从 *args 中删除它们.相反,您可以定义一个 Base 类,它与 object 不同,吸收/忽略参数:

class Base(object):def __init__(self, *args, **kwargs): 通过A类(基础):def __init__(self, *args, **kwargs):打印A"super(A, self).__init__(*args, **kwargs)B类(基础):def __init__(self, *args, **kwargs):打印B"super(B, self).__init__(*args, **kwargs)C(A)类:def __init__(self, arg, *args, **kwargs):打印 "C","arg=",argsuper(C, self).__init__(arg, *args, **kwargs)D(B)类:def __init__(self, arg, *args, **kwargs):打印 "D", "arg=",argsuper(D, self).__init__(arg, *args, **kwargs)E(C,D)类:def __init__(self, arg, *args, **kwargs):打印 "E", "arg=",argsuper(E, self).__init__(arg, *args, **kwargs)打印 "MRO:", [x.__name__ for x in E.__mro__]乙(10)

收益

MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object']E arg = 10参数 = 10一种D arg = 10乙

请注意,要使其正常工作,Base 必须是 MRO 中的倒数第二个类.

So I was following Python's Super Considered Harmful, and went to test out his examples.

However, Example 1-3, which is supposed to show the correct way of calling super when handling __init__ methods that expect different arguments, flat-out doesn't work.

This is what I get:

~ $ python example1-3.py 
MRO: ['E', 'C', 'A', 'D', 'B', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B
Traceback (most recent call last):
  File "Download/example1-3.py", line 27, in <module>
    E(arg=10)
  File "Download/example1-3.py", line 24, in __init__
    super(E, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 14, in __init__
    super(C, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 4, in __init__
    super(A, self).__init__(*args, **kwargs)
  File "Download/example1-3.py", line 19, in __init__
    super(D, self).__init__(arg, *args, **kwargs)
  File "Download/example1-3.py", line 9, in __init__
    super(B, self).__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters

It seems that object itself violates one of the best practices mentioned in the document, which is that methods which use super must accept *args and **kwargs.

Now, obviously Mr. Knight expected his examples to work, so is this something that was changed in recent versions of Python? I checked 2.6 and 2.7, and it fails on both.

So what is the correct way to deal with this problem?

解决方案

Sometimes two classes may have some parameter names in common. In that case, you can't pop the key-value pairs off of **kwargs or remove them from *args. Instead, you can define a Base class which unlike object, absorbs/ignores arguments:

class Base(object):
    def __init__(self, *args, **kwargs): pass

class A(Base):
    def __init__(self, *args, **kwargs):
        print "A"
        super(A, self).__init__(*args, **kwargs)

class B(Base):
    def __init__(self, *args, **kwargs):
        print "B"
        super(B, self).__init__(*args, **kwargs)

class C(A):
    def __init__(self, arg, *args, **kwargs):
        print "C","arg=",arg
        super(C, self).__init__(arg, *args, **kwargs)

class D(B):
    def __init__(self, arg, *args, **kwargs):
        print "D", "arg=",arg
        super(D, self).__init__(arg, *args, **kwargs)

class E(C,D):
    def __init__(self, arg, *args, **kwargs):
        print "E", "arg=",arg
        super(E, self).__init__(arg, *args, **kwargs)

print "MRO:", [x.__name__ for x in E.__mro__]
E(10)

yields

MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object']
E arg= 10
C arg= 10
A
D arg= 10
B

Note that for this to work, Base must be the penultimate class in the MRO.

这篇关于使用 super 的正确方法(参数传递)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆