关于函数:在python继承层次结构中管理args和kwargs

Manage both args and kwargs in a python inheritance hierarchy

本问题已经有最佳答案,请猛点这里访问。

有没有什么"好"的方法可以像我在这段代码中尝试的那样,在继承层次结构中管理arg和kwarg。我的意思是没有得到一个在Kwargs中有指定键的值或类似的东西…

应显示1 2 3 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()

语法不好:应为";"在*参数之后。

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

  • 当我尝试这个语法和child = Child(1, childArg2=2, 3, motherArg2=4)时,我得到syntaxerror:non-keyword arg,在keyword arg之后。
  • 当我尝试child = Child(1, 3, childArg2=2, motherArg2=4)时,我得到typeerror:uu init_uu()得到了关键字参数'childarg2'的多个值。

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

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

    但是,您无论如何都不能使用额外的位置参数,因为它们是由childArg2参数捕获的:

    1
    2
    3
    4
    >>> 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字典中获取关键字参数:

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

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

    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
    >>> 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

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

    1
    2
    3
    4
    1
    2
    3
    4

    但你也可以让它为Python2工作。您可以通过删除kwargs中的条目来完成这项操作,这些条目应该在您将它们传递给家长之前与孩子相关。

    代码(适用于python3):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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代码

    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 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()