我有一个Parent
类,其属性arg2
的默认值。我想创建一个子类Child
,它对同一个属性有不同的默认值。
我需要在*args
中使用**kwargs
和Child
。
我尝试了以下操作,但它无效:
class Parent(object):
def __init__(self, arg1='something', arg2='old default value'):
self.arg1 = arg1
self.arg2 = arg2
print('arg1:', self.arg1)
print('arg2:', self.arg2)
class Child(Parent):
def __init__(self, *args, **kwargs):
super(Child, self).__init__(*args, **kwargs)
self.arg2 = kwargs.pop('arg2', 'new value')
这不起作用。事实上,我得到了:
>>> c = Child()
arg1: something
arg2: default value # This is still the old value
>>> c.arg2
'new value' # Seems more or less ok
>>> c = Child('one', 'two')
arg1: one
arg2: two
>>> c.arg2
'new value' # This is wrong, it has overridden the specified argument 'two'
答案 0 :(得分:2)
您需要在super()
中设置默认值,然后再将其传递给args
;这很棘手,因为您需要确保class Child(Parent):
def __init__(self, *args, **kwargs):
if len(args) < 2 and 'arg2' not in kwargs:
kwargs['arg2'] = 'new value'
super(Child, self).__init__(*args, **kwargs)
中也没有相同的值:
super().__init__
这依赖于知道有多少参数可以填充。你必须使用from inspect import getargspec
class Child(Parent):
def __init__(self, *args, **kwargs):
super_init = super().__init__
argspec = getargspec(super_init)
arg2_index = argspec.args.index('arg2') - 1 # account for self
if len(args) < arg2_index and 'arg2' not in kwargs:
kwargs['arg2'] = 'new value'
super(Child, self).__init__(*args, **kwargs)
的内省来解决这个问题:
class Child(Parent):
def __init__(self, arg1='something', arg2='new value'):
super(Child, self).__init__(arg1=arg1, arg2=arg2)
您最好不要指定所有默认值:
while
答案 1 :(得分:2)
你实际上改变了班级的签名。基本上,用:
def foo(a=1, b=2):
...
您可以按位置,或按关键字调用:
foo(2, 3)
foo(a=2, b=3)
使用:
def bar(**kwargs):
...
你不能再使用位置参数调用:
bar(2, 3) # TypeError!
您的实际代码还有其他复杂因素,因为您的*args
占用了所有位置参数。
我能给你的最有力的建议是在覆盖方法时保留签名:
class Child(Parent):
def __init__(self, arg1='something', arg2='new value'):
super(Child, self).__init__(arg1=arg1, arg2=arg2)
这(很遗憾)并不是一个干嘛(不要重复自己),因为你可能喜欢 - 你必须指定'something'
两次。您可以将其转换为全局常量,或更改Parent.__init__
的签名。
或者,你可以做一些内省来处理父类的签名,以确保你以正确的方式传递正确的论点 - 但我非常怀疑它是什么?值得的。