Python2.7:当超级__init__创建它自己的子类的实例时的无限循环

时间:2013-06-10 18:29:37

标签: python oop inheritance python-2.7

我觉得这必须是一个愚蠢的问题 - 在这里。所以我愿意回答“这是屁股倒退,不要这样做,请试试这个: [正确的方式] ”。

我正在使用Python 2.7.5。

问题的一般形式

这会导致无限循环,除非Thesaurus(应用程序范围的单例)不调用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__() 1}}。

么?

2 个答案:

答案 0 :(得分:2)

好吧,我正在停下来查看你的代码,我只会根据你的说法做出答案:

  

我有一个基类,几乎我的应用程序中的每个其他类都扩展了(只是应用程序内部功能的一些基本约定;也许应该只是一个接口)。

这将是下面代码中的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模块只运行一次)

答案 1 :(得分:0)

简短的回答是:

不要从超类构造函数

实例化子类的实例

更长的回答:

如果您必须尝试这样做的动机是同义词库是一个单独的事实那么你最好在类(同义词库)中使用静态方法暴露单例并在需要单例时调用此方法