2012-09-11 34 views
4

我在努力尋找一個「Python化」的方式下面的類組織:是否有對所需屬性(OOP)的「pythonic」方法?

我有在其構造函數初始化性能的基類,例如:

class Animal(object): 
    def __init__(self, class_, species, is_domesticated): 
     self.class_ = class_ 
     self.species = species 
     self.is_domesticated = is_domesticated 

然後,當我繼承,我想「硬編碼」一個或多個這些性質,如下所示:因此

class Mammal(Animal): 
    def __init__(self, species, is_domesticated): 
     Animal.__init__(self, 'Mammal', species, is_domesticated) 

哺乳動物被實例化,像這樣:

monkey = Mammal('Primate', false) 

問題是,我想使用* args,以便在更改基類定義時保留任何派生類。因此哺乳動物的定義變爲:

class Mammal(Animal): 
    def __init__(self, *args): 
     Animal.__init(self, *(args + (class_='Mammal',))) 

哪個(不用說)看起來很可怕。一些提示將不勝感激=)

+2

從'進口this':顯式優於隱式。我會說你的第一次嘗試看起來不錯! –

+1

當你向它們也應該接受的基類中添加參數時,你並不是「僅僅離開派生類」。您只是通過不記錄參數來強化客戶端代碼作者。 –

+0

也許你可以使用默認的可選參數(如'is_deomesticated = False' ...)? –

回答

6

如果你在基類中只有一組固定的參數,沒有太多需要擔心可變參數。只要做你在第一個例子中所做的就可以了。如果你想能夠隨機地將參數添加到基類中,但是將它們添加爲位置參數並且沒有默認值,那就沒有希望了;你不能只是改變基類,並期望所有派生類繼續工作。

但是,有一個相當常見的中間情況,您可能有一大組屬性,其中的各種組合可能會傳遞給層次結構中的任何類。您可能希望將新參數添加到基類,但它們將具有默認值,以便派生類不需要明確知道它們;他們會優雅地降級到基類默認值。在這種情況下,使用**kwargs而不是*args通常更好。

class Animal(object): 
    def __init__(self, **kwargs): 
     self.class_ = kwargs['class_'] 
     self.species = kwargs['species'] 
     # etc. 
class Mammal(Animal): 
    def __init__(self, **kwargs): 
     Animal.__init__(self, class_="Mammal", **kwargs) 

這需要通過關鍵字來傳遞參數:

>>> Animal(class_='Fish', species='barracuda', is_domesticated=False) 
4: <__main__.Animal object at 0x0177ABF0> 
>>> Mammal(species="monkey", is_domesticated=False) 
5: <__main__.Mammal object at 0x0177AFB0> 

。 。 。但是如果有很多這樣的東西會更好,因爲如果你有10個不同的東西在位置上通過,那麼沒有人會記得通過它們的順序。這也意味着您可以輕鬆添加新的參數;沒有人必須知道列表中的哪個位置放置新的位置,他們可以通過關鍵字將它們添加到任何地方。

在Python 2中,您必須像上面那樣手動提取kwargs。在Python 3中,您可以使用keyword-only arguments使其更容易。

+0

您發佈您的答案,因爲我建議作爲評論! +1 –

0

那麼,你爲什麼不做你說的你想要的東西呢?使Mammal.__init__()採取*args參數,然後使用它。下面的代碼:

class Animal(object): 
    def __init__(self, class_, species, is_domesticated): 
     self.class_ = class_ 
     self.species = species 
     self.is_domesticated = is_domesticated 
    def __str__(self): 
     s_dom = "dom" if self.is_domesticated else "wild" 
     return ("Animal(%s, %s, %s)" % (self.class_, self.species, s_dom)) 

class Mammal(Animal): 
    def __init__(self, *args): 
     Animal.__init__(self, 'Mammal', *args) 

cat = Mammal("cat", True) 
print(cat) 

lion = Mammal("lion", False) 
print(lion) 

輸出:

Animal(Mammal, cat, dom) 
Animal(Mammal, lion, wild) 
相關問題