在python继承层次结构

时间:2016-06-15 08:54:07

标签: python function inheritance arguments

是否有任何“好”的方法来管理继承层次结构中的args和kwargs,就像我在这段代码中尝试过的那样。我的意思是没有在kwargs或类似的东西中获得具有指定键的值...

应该显示1 2 3 4

class Parent(object):
    def __init__(self, motherArg1, motherArg2=100):
        self.motherArg1 = motherArg1
        self.motherArg2 = motherArg2
    def printParent(self):
        print self.motherArg1
        print self.motherArg2

class Child(Parent):
    def __init__(self, childArg1, *args, childArg2=100, **kwargs): # Doesn't work here
        super(Child, self).__init__(*args, **kwargs)
        self.childArg1 = childArg1
        self.childArg2 = childArg2
    def printChild(self):
        print self.childArg1
        print self.childArg2

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()

语法不好:期望“);”在* args之后。

并且def __init__(self, childArg1, childArg2=100, *args, **kwargs)是正确的语法,但不起作用。

  1. 当我尝试使用此语法和child = Child(1, childArg2=2, 3, motherArg2=4)时,我得到 SyntaxError:关键字arg之后的非关键字arg
  2. 当我尝试child = Child(1, 3, childArg2=2, motherArg2=4)时,我得到 TypeError:__ init __()获得了关键字参数'childArg2'的多个值

2 个答案:

答案 0 :(得分:2)

在Python 2中,您必须将*args参数放在任何显式关键字参数之后:

def __init__(self, childArg1, childArg2=100, *args, **kwargs):

但是,您无法使用其他位置参数无论如何,因为它们被childArg2参数捕获:

>>> child = Child(1, 3, childArg2=2, motherArg2=4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() got multiple values for keyword argument 'childArg2'

您唯一的选择是从**kwargs字典中获取关键字参数:

def __init__(self, childArg1, *args, **kwargs):
    childArg2 = kwargs.pop('childArg2', 2)

这使childArg2仅作为显式关键字参数工作,*args捕获所有其他位置参数:

>>> class Parent(object):
...     def __init__(self, motherArg1, motherArg2=100):
...         self.motherArg1 = motherArg1
...         self.motherArg2 = motherArg2
...     def printParent(self):
...         print self.motherArg1
...         print self.motherArg2
...
>>> class Child(Parent):
...     def __init__(self, childArg1, *args, **kwargs):
...         childArg2 = kwargs.pop('childArg2', 2)
...         super(Child, self).__init__(*args, **kwargs)
...         self.childArg1 = childArg1
...         self.childArg2 = childArg2
...     def printChild(self):
...         print self.childArg1
...         print self.childArg2
...
>>> child = Child(1, 3, childArg2=2, motherArg2=4)
>>> child.printChild()
1
2
>>> child.printParent()
3
4

答案 1 :(得分:1)

当您将父级printChild重命名为printParent(并修复print s)时,它已在python 3中正常工作,如建议的那样:

1
2
3
4

但你也可以让它适用于python2。你可以通过删除kwargs中与儿童相关的条目,然后再将它们传递给父母。

代码(适用于python3):

class Parent(object):
    def __init__(self, motherArg1, motherArg2=100):
        self.motherArg1 = motherArg1
        self.motherArg2 = motherArg2
    def printParent(self):
        print(self.motherArg1)
        print(self.motherArg2)

class Child(Parent):
    def __init__(self, childArg1, *args, childArg2=100, **kwargs):
        super(Child, self).__init__(*args, **kwargs)
        self.childArg1 = childArg1
        self.childArg2 = childArg2
    def printChild(self):
        print(self.childArg1)
        print(self.childArg2)

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()

python2的代码

class Parent(object):
    def __init__(self, motherArg1, motherArg2=100):
        self.motherArg1 = motherArg1
        self.motherArg2 = motherArg2
    def printParent(self):
        print(self.motherArg1)
        print(self.motherArg2)

class Child(Parent):
    def __init__(self, childArg1, *args, **kwargs): 
        # this shows the concept, it can be formulated more elegantly
        # with @Martijn Pieters answer's 'pop':
        if 'childArg2' in kwargs:
            childArg2 = kwargs['childArg2']
            del kwargs['childArg2']
        else:
            childArg2 = 2
        super(Child, self).__init__(*args, **kwargs)
        self.childArg1 = childArg1
        self.childArg2 = childArg2
    def printChild(self):
        print(self.childArg1)
        print(self.childArg2)

child = Child(1, 3, childArg2=2, motherArg2=4)
child.printChild()
child.printParent()