使用 super 的正确方法(参数传递) [英] correct way to use super (argument passing)
问题描述
所以我关注了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屋!