Python继承:将arg与kwarg混淆

Python inheritance: confusing arg with kwarg

如果我运行以下代码:

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
class A(object) :

    def __init__(self, x, y, z=3.0):
        self.x = x
        self.y = y
        self.z = z

class B(A):

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


if __name__=="__main__":

    thing = B("a","b", 1, 2)

    print thing.x # expect 1
    print thing.y # expect 2
    print thing.z # expect 3
    print thing.a # expect a
    print thing.b # expect b
    print thing.c # expect c

相反,我得到:

1
2
3
4
5
6
Traceback (most recent call last):
  File"H:/Python/Random Scripts/python_inheritance.py", line 23, in <module>
    thing = B(1,2,"a","b")
  File"H:/Python/Random Scripts/python_inheritance.py", line 15, in __init__
    super(B, self).__init__(*args, **kwargs)
TypeError: __init__() takes at least 3 arguments (2 given)

似乎python正在将第三个参数"a"解析为kwarg argment c而不是arg。我怎样才能得到我所期望的行为?

我当然可以:

1
2
3
4
5
6
7
class B(A):

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

但从各个方面看都很可怕。


下面是代码中的两行,对齐后显示为每个名称分配的值:

1
2
3
def __init__(self, a,   b,  c="c", *args, **kwargs):

        thing = B("a","b", 1,     2)

如您所见,1被分配给c,在variadic args列表中只留下一个参数。问题是,在你假设的方式中,没有两个"类"的论据:虽然你把c称为"kwarg论据",但它实际上并没有被定义为"kwarg论据",这比a更重要。如果some_dict同时具有'a''c'条目,则可以通过调用B(b="b", **some_dict)来解决这两个问题。与args和kwargs之间的定义二分法不同,只有指定了默认值的参数和不指定默认值的参数。

我认为你是对的,你最好的选择是kwargs.pop()。我的代码中到处都是这样"可怕"的例子。