correct way to use super (argument passing)
所以我跟踪了python的super-considered有害代码,并测试了他的示例。
但是,示例1-3在处理需要不同参数的
这就是我得到的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ~ $ 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 |
似乎
现在,很明显,奈特先生希望他的示例能够起作用,那么这是在最近的Python版本中发生的变化吗?我检查了2.6和2.7,但都失败了。
那么解决这个问题的正确方法是什么呢?
有时两个类可能有一些共同的参数名。在这种情况下,不能从
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 | 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) |
产量
1 2 3 4 5 6 | MRO: ['E', 'C', 'A', 'D', 'B', 'Base', 'object'] E arg= 10 C arg= 10 A D arg= 10 B |
请注意,要使其生效,
如果你要有很多继承权(这里就是这样),我建议你使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class First(object): def __init__(self, *args, **kwargs): self.first_arg = kwargs.pop('first_arg') super(First, self).__init__(*args, **kwargs) class Second(First): def __init__(self, *args, **kwargs): self.second_arg = kwargs.pop('second_arg') super(Second, self).__init__(*args, **kwargs) class Third(Second): def __init__(self, *args, **kwargs): self.third_arg = kwargs.pop('third_arg') super(Third, self).__init__(*args, **kwargs) |
这是解决这些问题的最简单方法。
1 | third = Third(first_arg=1, second_arg=2, third_arg=3) |
正如在python的super()中所解释的,一种方法是让类接受它需要的参数,并传递其余的参数。因此,当调用链到达
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 | class A(object): def __init__(self, *args, **kwargs): print"A" super(A, self).__init__(*args, **kwargs) class B(object): 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__(*args, **kwargs) class D(B): def __init__(self, arg, *args, **kwargs): print"D","arg=",arg super(D, self).__init__(*args, **kwargs) class E(C,D): def __init__(self, arg, *args, **kwargs): print"E","arg=",arg super(E, self).__init__(*args, **kwargs) print"MRO:", [x.__name__ for x in E.__mro__] E(10, 20, 30) |