2012-06-24 59 views
3
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混亂的代碼中使用繼承,實例化,* ARGS,** kwargs

+0

「會發生什麼......」您是否想過嘗試查看實例的其他屬性? –

回答

6

你必須考慮它這樣:*args**kwargs「吃」全部由「常規」的論點它們之前留下的位置/關鍵字參數。如果你把它們放到最後,它們只會得到任何不符合「常規論點」的東西。

所以,當你寫FountainPen(5,1)什麼情況是,FountainPen.__init__被調用是這樣的:

  • self設置爲新創建的實例;
  • manufacturer獲取第一個參數,即5;
  • *args「吃」了所有其餘的位置參數,即只是1;所以args現在設置爲[1];
  • *kwargs會吃掉任何關鍵字參數,但沒有,所以它變成{}

它當時顯然,Pen.__init__被稱爲只有1作爲參數(除了self),並length仍設置爲默認值(None)。

0

在您的代碼5中分配給自變量manufacturer並且1將轉到*args

當不帶鍵的參數傳遞給函數時,必須首先提供顯式的參數。其餘的被傳遞給* args。爲了避免這種情況,呼喚你的構造函數時提供的關鍵字:

>>> instance_FP = FountainPen(mean_radius=5, length=1) 
+0

Tyler on'lenght' –

+0

@JonClements我修正了它。 –

2

Matteo Italia提到什麼是錯的,基本manufacturer是一個位置參數。您可以通過FountainPen__init__稍微改變以下修復:

def __init__(self, *args, manufacturer = "Waterman", **kwargs): 

這樣做會使manufacturer關鍵字參數,從而改變它,你將不得不撥打:

FountainPen(manufacturer="newval") 

注:不幸的是此語法(僅在*args參數後具有關鍵字唯一參數)僅在Python 3中有效。Jon Clements有一個solution可解決Python 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') 
+1

如果你想保持默認值的行爲,這可以修復得更好一點。使用:'self.manufacturer = kwargs。得到('製造商','沃特曼')' – JPvdMerwe

+0

@JPvdMerwe非常好的一點 - 沒有想到這一點!發佈編輯以反映您的建議 –