[英]Confusion in code using inheritance, instantiation, *args, **kwargs
class Pen(object):
def __init__(self, mean_radius = None, length = None):
self.usage = "Is used to apply ink trails to drawing surfaces"
self.mean_radius = mean_radius
self.length = length
class FountainPen(Pen):
def __init__(self, manufacturer = "Waterman", *args, **kwargs):
Pen.__init__(self, *args, **kwargs)
self.manufacturer = manufacturer
self.cartridge_state = "non-empty"
>>> instance_FP = FountainPen(5, 1)
>>> instance_FP.mean_radius
>>> print instance_FP.mean_radius
1
>>> print instance_FP.length
None
在FountainPen
的实例化中将整数5
作为参数传递时会发生什么情况? 为什么print instance_FP.mean_radius
返回1
而不是5
?
您必须这样认为: *args
和**kwargs
“吃掉”在它们前面的“常规”参数留下的所有位置/关键字参数。 如果把它们放在最后,它们只会得到不适合“常规参数”的任何东西。
因此,当您编写FountainPen(5,1)
,会发生FountainPen.__init__
调用FountainPen.__init__
情况:
self
设置为新创建的实例; manufacturer
获得第一个参数,即5; *args
“吃掉”所有剩余的位置参数,即仅1
; 因此args
现在设置为[1]
; *kwargs
会吃掉剩下的所有关键字参数,但是没有关键字,因此它变成{}
。 然后很明显, Pen.__init__
1
作为参数(除了self
)调用了Pen.__init__
,而length
仍设置为其默认值( None
)。
Matteo Italia的提法出了什么问题,基本上manufacturer
是一个立场论点。 您可以通过将FountainPen
的__init__
稍微更改为以下内容来修复它:
def __init__(self, *args, manufacturer = "Waterman", **kwargs):
这样做会使manufacturer
成为关键字参数,因此要更改它,您必须调用:
FountainPen(manufacturer="newval")
注意:不幸的是,这种语法(在*args
参数后仅具有关键字参数)仅在Python 3中有效。Jon Clements的解决方案可解决Python 2的此问题。
一个更优雅的解决方案是:
class FountainPen(Pen):
def __init__(self, *args, **kwargs):
Pen.__init__(self, *args, **kwargs)
self.manufacturer = kwargs.get('manufacturer', 'Waterman')
self.cartridge_state = "non-empty"
blah = FountainPen(5, 1, manufacturer='Waterman')
在您的代码中,将5分配给参数manufacturer
,将1分配给*args
。
将不带键的参数传递给函数时,必须首先提供显式参数。 其余的传递给* args。 为避免这种情况,请在调用构造函数时提供关键字:
>>> instance_FP = FountainPen(mean_radius=5, length=1)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.