为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

收到一只叮咚 2021-03-12 15:10:13
我觉得这一定是一个愚蠢的问题-此处不谈。因此,我很乐意回答“这是向后的,请不要这样做,请尝试以下方法:[正确的方法] ”。我正在使用Python 2.7.5。问题的一般形式这会导致无限循环,除非Thesaurus(应用程序范围内的单例)不调用Baseclass.__init__()class Baseclass():    def __init__(self):        thes = Thesaurus()        #do stuffclass Thesaurus(Baseclass):    def __init__(self):        Baseclass.__init__(self)        #do stuff我的具体情况我有一个基类,实际上我的应用程序中的所有其他类都可以扩展(只是一些应用程序内功能的基本约定;也许应该只是一个接口)。此基类旨在容纳一个Thesaurus类的单例,该类通过推断一些同义词(即{'yes':'yep', 'ok'})为用户输入提供一定的灵活性。但是由于子类调用超类的__init__(),而后者又创建了另一个子类,因此随之而来。不能称呼超类的__init__()工作效果很好,但我担心这只是一个幸运的巧合,而且我的Thesaurus类最终可能会被修改为需要其父类__init__()。
查看完整描述

2 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

好吧,我将停止查看您的代码,而我的答案只是基于您的意见:


我有一个基类,实际上我的应用程序中的所有其他类都可以扩展(只是一些应用程序内功能的基本约定;也许应该只是一个接口)。


这将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)

编辑:基本上,我在这里所做的是建立一个“基础”类,该类只是一个接口,该接口定义了其所有子类的预期行为。该类ThesaurusSingleton(我知道这是一个糟糕的名字)也正在实现该接口,因为您说过它也有,并且我不想讨论您的设计,所以您可能总是有奇怪的约束的充分理由。


最后,您是否真的需要在定义单例对象的类中实例化您的单例?尽管可能有一些骇人听闻的方法,但是通常会有更好的设计来避免出现“骇人听闻”的部分。


我的想法是,无论您创建单身人士,都应该明确地做到这一点。那就是“ Zen of python”:显式比隐式好。为什么?因为这样一来,阅读您的代码的人(也许六个月后便会成为您)将能够了解正在发生的事情以及编写该代码时您在想什么。如果您尝试使事情变得更隐式(例如使用复杂的元类和怪异的自继承),您可能会想知道这段代码在不到三周的时间内会做什么!


我并不是说要避免这种选择,而只是在没有简单选择的情况下才使用复杂的选择!


根据您所说的,我认为我提供的解决方案可以作为起点。但是当您专注于一些晦涩但不是非常有用的hacky东西而不是谈论您的设计时,我不确定我的示例是否合适,并向您提示了设计。


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>

并且您可以initClassWide在声明ThesaurusBase的模块级别调用该方法,因此,每当导入该模块时,该模块都会加载单例(导入机制确保python模块仅运行一次)。


查看完整回答
反对 回复 2021-03-31
?
慕勒3428872

TA贡献1848条经验 获得超6个赞

简短的答案是:

不要从超类构造函数实例化一个子类的实例

更长的答案:

如果您要这样做的动机是词库是一个单例事实,那么最好使用类(Thesaurus)中的静态方法公开该单例,并在需要该单例时调用此方法


查看完整回答
反对 回复 2021-03-31
  • 2 回答
  • 0 关注
  • 201 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信