如何在Python中向派生类的构造函数添加关键字参数?

时间:2014-12-14 17:58:09

标签: python-2.7 constructor keyword-argument

我想在派生类中添加关键字参数,但无法弄清楚如何去做。尝试显而易见的

class ClassA(some.package.Class):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)

class ClassB(ClassA):

    def __init__(self, *args, a='A', b='B', c='C', **kwargs):
        super(ClassB, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

失败,因为我无法列出ClassB __init__的参数。和

class ClassB(ClassA):

    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)
        self.a=a
        self.b=b
        self.c=c

当然不起作用,因为没有指定新的关键字。

如何为派生类的__init__添加关键字参数?

4 个答案:

答案 0 :(得分:7)

尝试这样做:

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

class ClassB(ClassA):
    def __init__(self, *args, **kwargs):            
        self.a = kwargs.pop('a', 'A')
        self.b = kwargs.pop('b', 'B')
        self.c = kwargs.pop('c', 'C')
        super(ClassB, self).__init__(*args, **kwargs)

有效地将关键字参数a,b和c添加到ClassB,同时将其他关键字参数传递给ClassA。

答案 1 :(得分:2)

您需要做的只是重新排列论据。

def __init__(self, a='A', b='B', c='C', *args, **kwargs):

答案 2 :(得分:2)

def __init__(self, a='A', b='B', c='C', *args, **kwargs):

的影响

使用具有上述签名的子类的构造函数修改OP的代码:

class BaseClass(object):
    def __init__(self, *args, **kwargs):
        self.args = args
        for k, v in kwargs.items():
            setattr(self, k, v)

class ClassA(BaseClass):
    def __init__(self, *args, **kwargs):
        super(ClassA, self).__init__(*args, **kwargs)

class ClassB(ClassA):
    def __init__(self, a='A', b='B', c='C', *args, **kwargs):
        self.a = a
        self.b = b
        self.c = c
        super(ClassA, self).__init__(*args, **kwargs)


A = ClassA('hello', 'world', myname='hal',myemail='hal@hal.hal')
B = ClassB('hello', 'world', myname='hal', myemail='hal@hal.hal')

print("CLASS A:", A.__dict__)
print("CLASS B:", B.__dict__)
# yields the following:
CLASS A: {'args': ('hello', 'world'), 'myname': 'hal', 'myemail': 'hal@hal.hal'}
CLASS B: {'args': (), 'myname': 'hal', 'a': 'hello', 'myemail': 'hal@hal.hal', 'c': 'C', 'b': 'world'}

代码不会抛出异常,但是,a,b& c现在是位置上传递给方法的前3个参数(忽略self),从两个对象的dicts中可以看出。

访问属性a,b& c显示此其他效果

>>> B.a # expect to see 'A'
'hello'
>>> B.b # similarly
'world'
>>> B.c # but this retails the default value
'C'

AFAIK,您不能仅为方法签名添加新的关键字参数。如果我错了,请纠正我。

然而,@ aknuds1和@Oleh Prypin都提供了有效地向子类添加新关键字参数的解决方案。 Oleh的解决方案更加聪明,但我发现aknuds1的版本更容易理解。

  • 来自kwargs dict的pop元素,合并为默认值
  • 使用setattr
  • 分配实例属性
  • 使用args,kwargs
  • 调用父构造函数

答案 3 :(得分:0)

使用Python 3.x,它使仅关键字参数有效。

或者使用此解决方法...

class ClassB(ClassA):
    def __init__(self, *args, **kwargs):
        for arg, default in [('a', 'A'), ('b', 'B'), ('c', 'C')]:
            setattr(self, arg, kwargs.pop(arg, default))
        super(ClassA, self).__init__(*args, **kwargs)