猿问

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

我觉得这一定是一个愚蠢的问题-此处不谈。因此,我很乐意回答“这是向后的,请不要这样做,请尝试以下方法:[正确的方法] ”。


我正在使用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__()。


收到一只叮咚
浏览 202回答 2
2回答

人到中年有点甜

好吧,我将停止查看您的代码,而我的答案只是基于您的意见:我有一个基类,实际上我的应用程序中的所有其他类都可以扩展(只是一些应用程序内功能的基本约定;也许应该只是一个接口)。这将ThesaurusBase在下面的代码中该基类旨在容纳一个词库类的单例,该类通过推断一些同义词(即{'yes':'yep','ok'})为用户输入提供一定的灵活性。那将是ThesaurusSingleton,您可以使用更好的名称进行调用并使其真正有用。class ThesaurusBase():&nbsp; &nbsp; def __init__(self, singleton=None):&nbsp; &nbsp; &nbsp; &nbsp; self.singleton = singleton&nbsp; &nbsp; def mymethod1(self):&nbsp; &nbsp; &nbsp; &nbsp; raise NotImplementedError&nbsp; &nbsp; def mymethod2(self):&nbsp; &nbsp; &nbsp; &nbsp; raise NotImplementedErrorclass ThesaurusSingleton(ThesaurusBase):&nbsp; &nbsp; def mymethod1(self):&nbsp; &nbsp; &nbsp; &nbsp; return "meaw!"class Thesaurus(TheraususBase):&nbsp; &nbsp; def __init__(self, singleton=None):&nbsp; &nbsp; &nbsp; &nbsp; TheraususBase.__init__(self, singleton)&nbsp; &nbsp; def mymethod1(self):&nbsp; &nbsp; &nbsp; &nbsp; return "quack!"&nbsp; &nbsp; def mymethod2(self):&nbsp; &nbsp; &nbsp; &nbsp; return "\\_o<"现在,您可以按以下方式创建对象:singleton = ThesaurusSingleton()thesaurus = Thesaurus(singleton)编辑:基本上,我在这里所做的是建立一个“基础”类,该类只是一个接口,该接口定义了其所有子类的预期行为。该类ThesaurusSingleton(我知道这是一个糟糕的名字)也正在实现该接口,因为您说过它也有,并且我不想讨论您的设计,所以您可能总是有奇怪的约束的充分理由。最后,您是否真的需要在定义单例对象的类中实例化您的单例?尽管可能有一些骇人听闻的方法,但是通常会有更好的设计来避免出现“骇人听闻”的部分。我的想法是,无论您创建单身人士,都应该明确地做到这一点。那就是“ Zen of python”:显式比隐式好。为什么?因为这样一来,阅读您的代码的人(也许六个月后便会成为您)将能够了解正在发生的事情以及编写该代码时您在想什么。如果您尝试使事情变得更隐式(例如使用复杂的元类和怪异的自继承),您可能会想知道这段代码在不到三周的时间内会做什么!我并不是说要避免这种选择,而只是在没有简单选择的情况下才使用复杂的选择!根据您所说的,我认为我提供的解决方案可以作为起点。但是当您专注于一些晦涩但不是非常有用的hacky东西而不是谈论您的设计时,我不确定我的示例是否合适,并向您提示了设计。edit2:还有另一种方法可以实现您想要的内容(但请确保这确实是您想要的设计)。您可能想使用将对类本身(而不是实例)起作用的类方法,从而使您能够存储自身的类范围的实例:>>> class ThesaurusBase:...&nbsp; &nbsp; &nbsp;@classmethod...&nbsp; &nbsp; &nbsp;def initClassWide(cls):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cls._shared = cls()...&nbsp;>>> class T(ThesaurusBase):...&nbsp; &nbsp; &nbsp;def foo(self):...&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;print self._shared...&nbsp;>>> ThesaurusBase.initClassWide()>>> t = T()>>> t.foo()<__main__.ThesaurusBase instance at 0x7ff299a7def0>并且您可以initClassWide在声明ThesaurusBase的模块级别调用该方法,因此,每当导入该模块时,该模块都会加载单例(导入机制确保python模块仅运行一次)。

慕勒3428872

简短的答案是:不要从超类构造函数实例化一个子类的实例更长的答案:如果您要这样做的动机是词库是一个单例事实,那么最好使用类(Thesaurus)中的静态方法公开该单例,并在需要该单例时调用此方法
随时随地看视频慕课网APP

相关分类

Python
我要回答