简体   繁体   English

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

[英]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.

相关问题 什么时候调用 Python 的 super().__init__()? - When to call Python's super().__init__()? python2.7:是否可以确定__init__是从子类调用还是只是正常调用? - python2.7: Is it possible to determine whether __init__ was called from a subclass or just normally? 在子类的__init__中设置Super的属性 - Setting a Super's property in a Subclass' __init__ 使用子类和super时__init__的参数 - Arguments to __init__ when using a subclass and super 当子类使用__init __()调用super()时,超类的对象在哪里/是什么? - When a subclass calls super() with __init__(), where/what is the superclass's object? 在python2.7中仍然具有“ __init __()关键字必须是字符串”的功能-ReviewBoard - Still having “__init__() keywords must be strings” in python2.7 - ReviewBoard 父类和子类之间的__init__参数不匹配 - __init__ argument mismatch between super and subclass Python超类__init __()? - Python super class __init__()? 如何重写子类中的属性,但在python2.7中维护超类的方法? - How to override attributes in subclass, but maintain methods of super class in python2.7? 即使我使用“ super()”,我也需要手动将属性从超类的“ __init__”传递到子类的“ __init__”吗? - Do I need to pass attributes from superclass's “__init__” to subclass's “__init__” manually, even if I use “super()”?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM