避免在子类中指定所有参数
我有一个类:
class A(object):
def __init__(self,a,b,c,d,e,f,g,...........,x,y,z)
#do some init stuff
还有一个子类,它需要一个额外的参数(就是最后那个 W
)。
class B(A):
def __init__(self.a,b,c,d,e,f,g,...........,x,y,z,W)
A.__init__(self,a,b,c,d,e,f,g,...........,x,y,z)
self.__W=W
写这么多重复的代码感觉很傻,比如把 B
的构造函数里的所有参数都传给 A
的构造函数。因为这样的话,每次修改 A
的构造函数时,就得在 B
的代码里改两个地方。
我在想,Python 里应该有一些方法可以处理这种情况,但我不知道。你能给我指个方向吗?
我最好的想法是给 A
做一个类似复制构造函数的东西,然后把 B
的代码改成:
class B(A):
def __init__(self,instanceOfA,W):
A.__copy_ctor__(self,instanceOfA)
self.__W=W
这样做能满足我的需求,因为我每次都是在给定父类的实例时创建子类。不过我不确定这样是否可行……
4 个回答
2
在某些情况下,如果传给 __init__
方法的参数有默认值,那么在子类中就可以避免重复写 __init__
方法的参数列表。
在这种情况下,__init__
方法可以把额外的参数传给另一个方法,而子类可以选择重写这个方法:
class A(object):
def __init__(self, a=1, b=2, c=3, d=4, *args, **kwargs):
self.a = a
self.b = b
# …
self._init_extra(*args, **kwargs)
def _init_extra(self):
"""
Subclasses can override this method to support extra
__init__ arguments.
"""
pass
class B(A):
def _init_extra(self, w):
self.w = w
7
编辑:根据Matt的建议,并考虑到gnibbler对位置参数方法的担忧;你可能需要检查一下,确保额外的子类特定参数被正确指定——这和Alex的回答类似:
class B(A):
def __init__(self, *args, **kwargs):
try:
self._w = kwargs.pop('w')
except KeyError:
pass
super(B,self).__init__(*args, **kwargs)
>>> b = B(1,2,w=3)
>>> b.a
1
>>> b.b
2
>>> b._w
3
原始回答:
和Matt的回答的思路一样,只是用super()
来代替。
使用super()
来调用父类的__init__()
方法,然后继续初始化子类:
class A(object):
def __init__(self, a, b):
self.a = a
self.b = b
class B(A):
def __init__(self, w, *args):
super(B,self).__init__(*args)
self.w = w
21
考虑到参数可以通过名称或者位置来传递,我会这样写代码:
class B(A):
def __init__(self, *a, **k):
if 'W' in k:
w = k.pop('W')
else:
w = a.pop()
A.__init__(self, *a, **k)
self._W = w