0

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

我正在使用 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类最终可能会被修改为要求它是 parent __init__()

建议?

4

2 回答 2

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)

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

最后,你真的需要在定义单例对象的类中实例化你的单例吗?尽管可能有一些骇人听闻的方式来做到这一点,但通常会有更好的设计来避免“骇人听闻”的部分。

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

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

根据你所说的,我认为我给出的解决方案可以作为一个起点。但是当您专注于一些晦涩但不是很有用的骇人听闻的东西而不是谈论您的设计时,我无法确定我的示例是否合适,并提示您进行设计。

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 模块仅运行一次的导入机制)。

于 2013-06-10T18:49:47.197 回答
0

简短的回答是:

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

更长的答案:

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

于 2013-06-10T20:47:28.900 回答