簡體   English   中英

Python2.7:當超級__init__創建它自己的子類的實例時的無限循環

[英]Python2.7: infinite loop when super __init__ creates an instance of it's own subclass

我覺得這必須是一個愚蠢的問題 - 在這里。 所以我願意回答“這是屁股倒退,不要這樣做,請試試這個: [正確的方式] ”。

我正在使用Python 2.7.5。

問題的一般形式

這會導致無限循環,除非Thesaurus (app-wide singleton)不調用Baseclass.__init__()

class Baseclass():
    def __init__(self):
        thes = Thesaurus()
        #do stuff

class Thesaurus(Baseclass):
    def __init__(self):
        Baseclass.__init__(self)
        #do stuff

我的具體案例

我有一個基類,幾乎我的應用程序中的每個其他類都擴展(只是應用程序中的功能的一些基本約定;也許應該只是一個接口)。 這個基類意味着容納一個Thesaurus類的單例,通過推斷一些同義詞來賦予用戶輸入一些靈活性(即。 {'yes':'yep', 'ok'} )。

但是由於子類調用了超類的__init__() ,而后者又創建了另一個子類,所以循環接着。 調用超類的__init__()工作正常,但我擔心這只是一個幸運的巧合,並且我的Thesaurus類最終可能被修改為需要它的父__init__()

建議嗎?

好吧,我停下來查看你的代碼,我只是根據你的說法做出答案:

我有一個基類,幾乎我的應用程序中的每個其他類都擴展(只是應用程序中的功能的一些基本約定;也許應該只是一個接口)。

這將是下面代碼中的ThesaurusBase

這個基類意味着容納一個同義詞類的單例,通過推斷一些同義詞來賦予用戶輸入一些靈活性(即。{'yes':'yep','ok'})。

那就是ThesaurusSingleton ,你可以用一個更好的名字來調用它並使其真正有用。

class ThesaurusBase():
    def __init__(self, singleton=None):
        self.singleton = singleton

    def mymethod1(self):
        raise NotImplementedError

    def mymethod2(self):
        raise NotImplementedError

class ThesaurusSingleton(ThesaurusBase):
    def mymethod1(self):
        return "meaw!"

class Thesaurus(TheraususBase):
    def __init__(self, singleton=None):
        TheraususBase.__init__(self, singleton)

    def mymethod1(self):
        return "quack!"

    def mymethod2(self):
        return "\\_o<"

現在您可以按如下方式創建對象:

singleton = ThesaurusSingleton()
thesaurus = Thesaurus(singleton)

編輯:基本上,我在這里所做的是構建一個“Base”類,它只是一個定義其所有子類的預期行為的接口。 ThesaurusSingleton (我知道這是一個可怕的名字)也在實現該接口,因為你說它也有,我不想討論你的設計,你可能總是有很好的理由來制造奇怪的約束。

最后,你真的需要在定義單例對象的類中實例化你的單例嗎? 雖然可能有一些hackish方式這樣做,但通常有一個更好的設計,避免“hackish”部分。

我認為無論你創建單身,你應該更明確地做到這一點。 這就是“蟒蛇之禪”:明確比隱含更好。 為什么? 因為那時人們閱讀你的代碼(可能是你在六個月內)將能夠理解你在編寫代碼時發生了什么以及你在想什么。 如果你試圖讓事情變得更隱含(比如使用復雜的元類和奇怪的自我繼承),你可能會想知道這段代碼在不到三周的時間里會做什么!

我並沒有說明要避免這種選擇,而只是在你使用簡單的東西時才使用復雜的東西!

根據你的說法,我認為我給出的解決方案可以作為一個起點。 但是當你專注於一些模糊的,但不是非常有用的hackish東西而不是談論你的設計時,我不能確定我的例子是否合適,並暗示你的設計。

edit2:還有另一種方法來實現你想要的東西(但要確保它真的是你想要的設計)。 您可能希望使用一個類方法來處理類本身(而不是實例),從而使您能夠存儲自身的類范圍實例:

>>> class ThesaurusBase:
...     @classmethod
...     def initClassWide(cls):
...         cls._shared = cls()
... 
>>> class T(ThesaurusBase):
...     def foo(self):
...         print self._shared
... 
>>> ThesaurusBase.initClassWide()
>>> t = T()
>>> t.foo()
<__main__.ThesaurusBase instance at 0x7ff299a7def0>

並且您可以在聲明ThesaurusBase的模塊級別調用initClassWide方法,因此無論何時導入該模塊,它都將加載單例(導入機制確保python模塊僅運行一次)。

簡短的回答是:

不要從超類構造函數中實例化子類的實例

更長的答案:

如果您必須嘗試這樣做的動機是同義詞庫是一個單例,那么你最好在類(同義詞庫)中使用靜態方法暴露單例並在需要單例時調用此方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM