[英]Python2.7: infinite loop when super __init__ creates an instance of it's own subclass
I have the sense that this must be kind of a dumb question—nub here. 我觉得这必须是一个愚蠢的问题 - 在这里。 So I'm open to an answer of the sort "This is ass-backwards, don't do it, please try this: [proper way] ". 所以我愿意回答“这是屁股倒退,不要这样做,请试试这个: [正确的方式] ”。
I'm using Python 2.7.5. 我正在使用Python 2.7.5。
General Form of the Problem 问题的一般形式
This causes an infinite loop unless Thesaurus
(an app-wide singleton) does not call Baseclass.__init__()
这会导致无限循环,除非Thesaurus
(app-wide singleton)不调用Baseclass.__init__()
class Baseclass():
def __init__(self):
thes = Thesaurus()
#do stuff
class Thesaurus(Baseclass):
def __init__(self):
Baseclass.__init__(self)
#do stuff
My Specific Case 我的具体案例
I have a base class that virtually every other class in my app extends (just some basic conventions for functionality within the app; perhaps should just be an interface). 我有一个基类,几乎我的应用程序中的每个其他类都扩展(只是应用程序中的功能的一些基本约定;也许应该只是一个接口)。 This base class is meant to house a singleton of a Thesaurus
class that grants some flexibility with user input by inferring some synonyms (ie. {'yes':'yep', 'ok'}
). 这个基类意味着容纳一个Thesaurus
类的单例,通过推断一些同义词来赋予用户输入一些灵活性(即。 {'yes':'yep', 'ok'}
)。
But since the subclass calls the superclass's __init__()
, which in turn creates another subclass, loops ensue. 但是由于子类调用了超类的__init__()
,而后者又创建了另一个子类,所以循环接着。 Not calling the superclass's __init__()
works just fine, but I'm concerned that's merely a lucky coincidence, and that my Thesaurus
class may eventually be modified to require it's parent __init__()
. 不调用超类的__init__()
工作正常,但我担心这只是一个幸运的巧合,并且我的Thesaurus
类最终可能被修改为需要它的父__init__()
。
Advice? 建议吗?
Well, I'm stopping to look at your code, and I'll just base my answer on what you say: 好吧,我停下来查看你的代码,我只是根据你的说法做出答案:
I have a base class that virtually every other class in my app extends (just some basic conventions for functionality within the app; perhaps should just be an interface). 我有一个基类,几乎我的应用程序中的每个其他类都扩展(只是应用程序中的功能的一些基本约定;也许应该只是一个接口)。
this would be ThesaurusBase
in the code below 这将是下面代码中的ThesaurusBase
This base class is meant to house a singleton of a Thesaurus class that grants some flexibility with user input by inferring some synonyms (ie. {'yes':'yep', 'ok'}). 这个基类意味着容纳一个同义词类的单例,通过推断一些同义词来赋予用户输入一些灵活性(即。{'yes':'yep','ok'})。
That would be ThesaurusSingleton
, that you can call with a better name and make it actually useful. 那就是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<"
now you can create your objects as follows: 现在您可以按如下方式创建对象:
singleton = ThesaurusSingleton()
thesaurus = Thesaurus(singleton)
edit: Basically, what I've done here is build a "Base" class that is just an interface defining an expected behavior for all its children classes. 编辑:基本上,我在这里所做的是构建一个“Base”类,它只是一个定义其所有子类的预期行为的接口。 The class ThesaurusSingleton
(I know that's a terrible name) is also implementing that interface, because you said it had too and I did not want to discuss your design, you may always have good reasons for weird constraints. 类ThesaurusSingleton
(我知道这是一个可怕的名字)也在实现该接口,因为你说它也有,我不想讨论你的设计,你可能总是有很好的理由来制造奇怪的约束。
And finally, do you really need to instantiate your singleton inside the class that is defining the singleton object? 最后,你真的需要在定义单例对象的类中实例化你的单例吗? Though there may be some hackish way to do so, there's often a better design that avoids the "hackish" part. 虽然可能有一些hackish方式这样做,但通常有一个更好的设计,避免“hackish”部分。
What I think is that however you create your singleton, you should better do it explicitly. 我认为无论你创建单身,你应该更明确地做到这一点。 That's in the "Zen of python": explicit is better than implicit. 这就是“蟒蛇之禅”:明确比隐含更好。 Why? 为什么? because then people reading your code (and that might be you in six months) will be able to understand what's happening and what you were thinking when you wrote that code. 因为那时人们阅读你的代码(可能是你在六个月内)将能够理解你在编写代码时发生了什么以及你在想什么。 If you try to make things more implicit (like using sophisticated meta classes and weird self-inheritance) you may wonder what this code does in less than three weeks! 如果你试图让事情变得更隐含(比如使用复杂的元类和奇怪的自我继承),你可能会想知道这段代码在不到三周的时间里会做什么!
I'm not telling to avoid that kind of options, but to only use sophisticated stuff when you're out of simple ones! 我并没有说明要避免这种选择,而只是在你使用简单的东西时才使用复杂的东西!
Based on what you said I think the solution I gave can be a starting point. 根据你的说法,我认为我给出的解决方案可以作为一个起点。 But as you focus on some obscure, yet not very useful hackish stuff instead of talking about your design, I can't be sure if my example is that appropriate, and hint you on the design. 但是当你专注于一些模糊的,但不是非常有用的hackish东西而不是谈论你的设计时,我不能确定我的例子是否合适,并暗示你的设计。
edit2: There's an another way to achieve what you say you want (but be sure that's really the design you want). edit2:还有另一种方法来实现你想要的东西(但要确保它真的是你想要的设计)。 You may want to use a class method that will act on the class itself (instead of the instances) and thus enable you to store a class-wide instance of itself: 您可能希望使用一个类方法来处理类本身(而不是实例),从而使您能够存储自身的类范围实例:
>>> 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>
and you can call the initClassWide
method at the module level of where you declare ThesaurusBase, so whenever you import that module, it will have the singleton loaded (the import mechanism ensuring that python modules are run only once). 并且您可以在声明ThesaurusBase的模块级别调用initClassWide
方法,因此无论何时导入该模块,它都将加载单例(导入机制确保python模块仅运行一次)。
the short answer is: 简短的回答是:
do not instantiate an instance of a sub class from the super class constructor 不要从超类构造函数中实例化子类的实例
longer answer: 更长的答案:
if the motive you have to try to do this is the fact the Thesaurus is a singleton then you'll be better off exposing the singleton using a static method in the class (Thesaurus) and calling this method when you need the singleton 如果您必须尝试这样做的动机是同义词库是一个单例,那么你最好在类(同义词库)中使用静态方法暴露单例并在需要单例时调用此方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.