2011-05-23 70 views
1

給定任意對象:幫助與Python繼承

class Val(object): 
    def __init__(self): 
     this_val = 123 

我想創建具有是屬性的抽象基類Val()

class A(object): 
    foo = Val() 

我希望,當我的孩子繼承該類,他們將獲得Val()的副本。例如:

class B(A): 
    pass 
class C(A): 
    pass 

我希望以下行爲:

>>> b = B() 
>>> c = C() 
>>> c.foo.this_val = 456 
>>> b.foo.this_val 
123 

而是我得到:

>>> b.this_val 
456 

我明白,我可能只是self.foo = Val()INIT實現該行爲,但我有一個要求,即foo仍然是一個屬性(它是在Django的模型管理器)。任何人都可以爲此提出解決方法嗎?

編輯:我真正需要的是能夠訪問該值作爲一個類的屬性,所以我期望的行爲是:

>>> C.foo.this_val = 456 
>>> B.foo.this_val 
123 

回答

2

也許使用descriptor會滿足您的要求:

class Val(object): 
    def __init__(self): 
     self.this_val = 123 

class ValDesc(object): 
    def __init__(self): 
     self.cls_lookup = {} 

    def __get__(self, obj, objtype=None): 
     return self.cls_lookup.setdefault(objtype, Val()) 

class A(object): 
    foo = ValDesc() 

class B(A): 
    pass 
class C(A): 
    pass 

現在,只要你確保你沒有設置實例屬性您的任何物體的「富」,他們將有一類屬性是個體對每個子類:

b = B() 
c = C() 
cc = C() 
c.foo.this_val = 456 
print c.foo.this_val # 456 
print cc.foo.this_val # 456 
print b.foo.this_val # 123 

編輯:隨着我幾個小時前做出的修改,改變tr他在__get__關鍵是objtype而不是obj.__class__,訪問類時直接屬性,這也適用:

print B.foo.this_val # 123 
print C.foo.this_val # 456 
0

一舉兩得。

使其成爲類屬性,還將其初始化爲__init__函數中的新實例。這樣存儲的參考文獻就不是共享的參考文獻。

+0

我需要引用它的屬性,雖然。我想做'C.foo.this_val'和'B.foo.this_val'並得到不同的結果。對不起,如果不明確。我沒有實例:( – Bacon 2011-05-23 06:43:40

+0

然後在個別類定義中覆蓋它呢? – Amber 2011-05-23 06:47:47

+0

我真的很希望不要這樣做。必須有一些模糊的python私有方法,我可以重寫以達到這個目的? – Bacon 2011-05-23 06:50:15

4

屬性foo只有存在於A。您將不得不使用元類爲每個類添加一個新的Val

class Val(object): 
    def __init__(self): 
     self.this_val = 123 

class MC(type): 
    def __init__(self, name, bases, d): 
    super(MC, self).__init__(name, bases, d) 
    self.foo = Val() 

class A(object): 
    __metaclass__ = MC 

class B(A): 
    pass 

B.foo.this_val = 456 
print A.foo.this_val 
print B.foo.this_val