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
在5
实例化中作为参数传递的整数FountainPen
会发生什么?
为什么print instance_FP.mean_radius
会返回1
而不是5
?
答案 0 :(得分:6)
你必须这样认为:*args
和**kwargs
“吃掉”它们之前的“常规”参数留下的所有位置/关键字参数。如果你把它们放在最后,它们只会得到任何不符合“常规参数”的东西。
所以,当你写FountainPen(5,1)
时,会发生FountainPen.__init__
被调用的事情:
self
设置为新创建的实例; manufacturer
获取第一个参数,即5; *args
“吃掉”所有剩余的位置参数,即1
;因此,args
现已设置为[1]
; *kwargs
会留下任何关键字参数,但没有,所以它变为{}
。很明显,调用Pen.__init__
仅使用1
作为参数(self
除外),length
仍然设置为其默认值(None
)。
答案 1 :(得分:2)
Matteo Italia提到了什么是错的,基本上manufacturer
是一个位置论证。您可以稍微将FountainPen
的{{1}}更改为以下内容来解决此问题:
__init__
执行此操作会使def __init__(self, *args, manufacturer = "Waterman", **kwargs):
成为关键字参数,因此要更改它,您必须调用:
manufacturer
注意:不幸的是,这种语法(在FountainPen(manufacturer="newval")
参数之后只有关键字参数)只在Python 3中有效.Jon Clements有一个solution可以解决Python 2的这个问题。
答案 2 :(得分: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')
答案 3 :(得分:0)
在您的代码中,5分配给参数manufacturer
,1分配给*args
。
将没有键的参数传递给函数时,必须首先提供显式的参数。其余的传递给* args。为避免这种情况,请在调用构造函数时提供关键字:
>>> instance_FP = FountainPen(mean_radius=5, length=1)