2012-07-17 40 views
3

我有很多描述層次結構的Python類型,它們的屬性越來越具體。而不是試圖去描述它的話,這裏有一個例子:如何在Python中沒有is-a關係的情況下共享屬性?

class A: 
    @property 
    def prop1(self): 
     return self._prop1 

class B: 
    @property 
    def prop1(self): 
     return self._prop1 

    @property 
    def prop2(self): 
     return self._prop2 

class C: 
    @property 
    def prop1(self): 
     return self._prop1 

    @property 
    def prop2(self): 
     return self._prop2 

    @property 
    def prop3(self): 
     return self._prop3 

因此,當你走在班級名單,B擁有所有的A的屬性,然後一些額外的人的。 C具有B的所有屬性,然後是一些額外的屬性,依此類推。如果可能,我想盡量減少上述定義的重複。

一個明顯的解決方案是使用繼承,使BA的一個子類等等。但是,這些類型的語義不遵循is-a關係;我不想isinstance(bObject, A)True。在Python中是否有另一種方式直接允許這種不使用子類的屬性共享?

+0

您可以使用組合而不是子類。 – TheZ 2012-07-17 16:08:44

+0

我想你的意思是我可以在每個'B'內部放置一個'A',然後重新實現''''''''''從''A''實例拉取屬性訪問器。這是我們想到的另一種解決方案,但這看起來不像上面所示的那樣更緊湊。 – 2012-07-17 16:10:04

+0

爲什麼你真的關心'isinstance'返回什麼?你真的有一個很好的理由來永遠調用'isinstance'嗎? – geoffspear 2012-07-17 16:13:54

回答

7

您可以使用一個裝飾:

def has_prop1(cls): 
    @property 
    def prop1(self): 
     return self._prop1 

    cls.prop1 = prop1 

    return cls 

@has_prop1 
class A(object): 
    pass 

合成會是這樣的:

@has_prop1 
@has_prop2 
class B(object): 
    pass 

甚至是這樣的:

def has_many_properties(cls): 
    return has_prop1(has_prop2(has_prop3(cls))) 

@has_many_properties 
class C(object): 
    pass 
+0

非常好的解決方案。 – 2012-07-17 16:21:49

0

你說「我不想說謊,並說,如果C實際上沒有,那麼C就是A,這些類型的特徵不符合子類的語義。「以你模糊的例子來說,目前還不清楚該走哪條路。

如果你說這是因爲有一個在class A附加功能並不適用於class C,那麼我會組成扯起了階級的財產的一部分,所以你必須ABCAPropsBProps,和CProps分別給出了屬性類的適當繼承關係。

如果沒有這樣的附加功能,而這不僅僅是巧合的屬性建立你帶路,然後精神上重命名class Aclass ProvidesProp1,注意class C是-A提供prop1類,並接受class C因此是-a class A

相關問題