【问题标题】:Manage both args and kwargs in a python inheritance hierarchy [duplicate]在 python 继承层次结构中管理 args 和 kwargs [重复]
【发布时间】:2016-10-16 06:48:18
【问题描述】:

有没有像我在这段代码中尝试过的那样在继承层次结构中管理 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: non-keyword arg after keyword arg
  2. 当我尝试 child = Child(1, 3, childArg2=2, motherArg2=4) 时,我得到 TypeError: __init__() got multiple values for keyword argument 'childArg2'

【问题讨论】:

  • edit 将格式正确的内容包含在问题本身中。在这种情况下,你会得到什么输出很明显,但是minimal reproducible example 是一个很好的习惯。

标签: python function inheritance arguments


【解决方案1】:

在 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

【讨论】:

    【解决方案2】:

    当您将父级的 printChild 重命名为 printParent(并修复 prints)时,它已经在 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()
    

    【讨论】:

    • 由于 OP 使用显式的 objectprint 语句,更不用说报告他们的代码 不起作用 工作,很明显他们是使用 2.x。告诉他们它在 3.x 中有效并没有多大用处。
    • 你是对的。我现在添加了一个 python 2 版本
    • 不,你说它适用于 Python 3,所以也许我更喜欢更改我的 python 版本。谢谢!
    猜你喜欢
    • 2022-09-22
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多