Python2.7:超级初始化创建其实例时的无限循环';s自己的子类

Python2.7:超级初始化创建其实例时的无限循环';s自己的子类,python,oop,inheritance,python-2.7,Python,Oop,Inheritance,Python 2.7,我觉得这一定是个愚蠢的问题。所以我愿意接受这样的回答:“这是一个倒退,不要这样做,请试试这个:[正确的方式]” 我正在使用Python 2.7.5 问题的一般形式 这会导致无限循环,除非同义词库(应用程序范围的单例)不调用基类 我的具体案例 我有一个基类,我的应用程序中几乎所有其他类都会扩展它(只是应用程序中功能的一些基本约定;也许应该只是一个接口)。这个基类是用来存放同义词库类的一个单例,该类通过推断一些同义词(即{'yes':'yep','ok'})为用户输入提供一定的灵活性 但是,由于子类

我觉得这一定是个愚蠢的问题。所以我愿意接受这样的回答:“这是一个倒退,不要这样做,请试试这个:[正确的方式]”

我正在使用Python 2.7.5

问题的一般形式

这会导致无限循环,除非
同义词库
(应用程序范围的单例)不调用
基类

我的具体案例

我有一个基类,我的应用程序中几乎所有其他类都会扩展它(只是应用程序中功能的一些基本约定;也许应该只是一个接口)。这个基类是用来存放
同义词库
类的一个单例,该类通过推断一些同义词(即
{'yes':'yep','ok'}
)为用户输入提供一定的灵活性

但是,由于子类调用了超类的
\uuuu init\uuuu()
,从而又创建了另一个子类,因此循环随之发生。不调用超类的
\uuuu init\uuuu()
效果很好,但我担心这只是一个幸运的巧合,我的
同义词库
类最终可能会被修改为需要它的父类
\uuuuu init()


建议?

好吧,我停下来看看你的代码,我会根据你说的回答:

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

这将是下面代码中的
ThesaurusBase

这个基类用于容纳同义词库类的一个单例,通过推断一些同义词(例如,{'yes':'yep','ok'}),该类为用户输入提供了一定的灵活性

这将是
叙词表singleton
,你可以用一个更好的名字来调用它,让它变得实际有用

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<"
编辑: 基本上,我在这里所做的是构建一个“基类”,它只是一个定义其所有子类的预期行为的接口。ThesaurusSingleton类(我知道这是个糟糕的名字)也实现了这个接口,因为你说它也实现了,我不想讨论你的设计,你可能总是有很好的理由来解释奇怪的约束

最后,您真的需要在定义singleton对象的类中实例化您的singleton吗?虽然可能有一些黑客的方式来做到这一点,但通常有更好的设计来避免“黑客”部分

我的想法是,无论您如何创建您的单例,您最好明确地执行它。这就是“python禅”:显式比隐式好。为什么?因为这样,阅读你的代码的人(可能在六个月后就是你)将能够理解正在发生的事情以及你在编写代码时的想法。如果您试图使事情更加隐式(比如使用复杂的元类和奇怪的自继承),您可能会想知道这段代码在不到三周的时间内做了什么

我不是说要避免这种选择,而是说只有在你没有简单的东西时才使用复杂的东西

根据你所说的,我认为我给出的解决方案可以作为一个起点。但是,当你专注于一些模糊的,但不是非常有用的黑客的东西,而不是谈论你的设计,我不能确定我的例子是否是适当的,并提示你的设计

编辑2: 有另一种方法可以实现你所说的你想要的(但要确保这就是你想要的设计)。您可能希望使用作用于类本身(而不是实例)的类方法,从而使您能够存储自身的类范围实例:

>>> 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>
>>类别同义词库:
...     @类方法
...     def初始化类范围(cls):
...         cls._shared=cls()
... 
>>>T类(同义词库):
...     def foo(self):
...         打印自我共享
... 
>>>ThesaurusBase.initClassWide()
>>>t=t()
>>>傅先生()
您可以在声明同义词库的模块级调用
initClassWide
方法,因此每当您导入该模块时,它都会加载singleton(导入机制确保python模块只运行一次)。

简短的回答是:

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

详细回答:


如果您必须尝试这样做的动机是同义词库是一个单例,那么您最好在类(同义词库)中使用静态方法公开该单例,并在需要单例时调用该方法。

为什么要在父项的初始值设定项中创建子项的实例?因为它是单例;只有一个实例应该存在,扩展
Baseclass
的所有东西都应该可以访问它,并且从应用程序初始化的那一刻起就需要它。但我愿意接受关于如何更好地实施这一点的建议!:)为什么对
基类的调用在子类的
之外?你的代码很奇怪。这些应该是函数还是类?两者都使用了
def
关键字。推荐阅读/学习:诚然,我发现这很难理解,所以如果我有误解,请原谅。但是如果我读对了,它仍然不允许我在
同义词库中创建
同义词库
实例。理想情况下,该对象将可用于
同义词库中的后续函数调用。(这并不是忘恩负义,我只是不确定我是否理解!)因此,不,该对象不会自动提供给基于同义词库的其他对象。您必须将该单例作为参数提供给所有基于
同义词库的实例。这就清楚地表明,您的所有对象都使用相同的对象,不能更改。确实,这就是StackExchange的精神,非常感谢。这项努力是令人沮丧的
singleton = ThesaurusSingleton()
thesaurus = Thesaurus(singleton)
>>> 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>