2012-12-10 68 views
1

我有Base類。我想擴展它的功能Derived。我正打算寫:與繼承共享基礎對象

class Derived(Base): 
    def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2): 
    super().__init__(base_arg1, base_arg2) 
    # ... 
    def derived_method1(self): 
    # ... 

有時候,我已經有一個Base實例,我想創建一個基於它Derived實例,即Derived實例共享Base對象(不重新創建它從頭開始)。我想我可以寫一個靜態方法來做到這一點:

b = Base(arg1, arg2) # very large object, expensive to create or copy 
d = Derived.from_base(b, derived_arg1, derived_arg2) # reuses existing b object 

但似乎不可能。要麼我錯過了一個方法來完成這項工作,或者(更可能)我錯過了一個很大的原因,爲什麼它不能被允許工作。有人可以解釋它是哪一個?

[當然,如果我使用了組合而不是繼承,這將很容易做到。但我希望避免一切Base方法Derived代表團通過__getattr__]

+0

- 這是沒有意義的。實例化Derived類時沒有Base實例。只有一個Derived對象,所以沒有什麼可以共享或重新創建。我認爲你不應該繼承Base。 –

+0

另外,由於Base和Derived對'__init__'有不同的參數,所以一般情況下應避免使用'super()'。 –

+0

@LennartRegebro:關於你的第一條評論,我試圖分享的'Base'實例是'b'。它是在我試圖創建一個Derived實例之前創建的。 – max

回答

2

依靠你的Base類與base_arg1base_arg2做。

class Base(object): 
    def __init__(self, base_arg1, base_arg2): 
     self.base_arg1 = base_arg1 
     self.base_arg2 = base_arg2 
     ... 

class Derived(Base): 
    def __init__(self, base_arg1, base_arg2, derived_arg1, derived_arg2): 
     super().__init__(base_arg1, base_arg2) 
     ... 

    @classmethod 
    def from_base(cls, b, da1, da2): 
     return cls(b.base_arg1, b.base_arg2, da1, da2) 
+0

這將工作,但只有'__init__'是一個便宜的方法,只是將其參數分配給實例。不幸的是,這遠非如此。這是'Base'實例創建昂貴的主要原因。 – max

+0

@max我明白'Base'很貴,但爲了存儲2個額外的屬性,將2行代碼添加到'__init__'會產生什麼問題? –

+0

'base_arg1'是一個文件名,'base_arg2'是格式描述,'Base .__ init__'解析(通常是巨大的)文件並將結果存儲在內部數據結構中。 – max

1

的另一種方法阿列克謝的答案(我+1)是通過基礎對象在base_arg1參數,並進行檢查,無論是濫用傳遞的基本對象(如果是的實例基類)。另一種填料可以在技術上可選(如None),並在代碼內部決定時明確檢查。

區別在於只有參數類型決定了要使用兩種可能的創建方式中的哪一種。如果不能在源代碼中明確地捕獲對象的創建,這是必要的(例如,某些結構包含混合的參數元組,其中一些元素具有初始值,其中一些元素具有對現有對象的引用。可能需要傳遞參數作爲關鍵字參數:

d = Derived(b, derived_arg1=derived_arg1, derived_arg2=derived_arg2) 

更新時間:對於初始類的共享的內部結構,可以使用兩種方法但是,必須注意的一個事實,即如果其中一個對象試圖修改共享數據,通常會發生有趣的事情。

1

在這裏要清楚,我會做一個ans用代碼。 pepr談到這個解決方案,但代碼總是比英語更清晰。在這種情況下基本不應該被繼承,但它應該是衍生的一員:「這股基對象(不從頭開始重新創建)一個Derived實例」

class Base(object): 
    def __init__(self, base_arg1, base_arg2): 
     self.base_arg1 = base_arg1 
     self.base_arg2 = base_arg2 

class Derived(object): 
    def __init__(self, base, derived_arg1, derived_arg2): 
     self.base = base 
     self.derived_arg1 = derived_arg1 
     self.derived_arg2 = derived_arg2 

    def derived_method1(self): 
     return self.base.base_arg1 * self.derived_arg1