[英]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.