为什么在一个类中需要Thread?

2024-09-26 17:45:21 发布

您现在位置:Python中文网/ 问答频道 /正文

当我创建一个threading.Thread类时,为什么要强制使用threading.Thread.__init__(self)或{}?

例如:

class Threader(threading.Thread):
    def __init__(self, _fp, _q):
        threading.Thread.__init__(self)
        self.path = _fp
        self.queue = _q

    def run(self):
        # Do stuff

或者

^{pr2}$

两种方法都有效,而且做的事情大致相同。但是,如果我删除.__init__()方法中的任何一个,我将在堆栈中收到:from thread.start(): thread.__init__() not called

不应该定义我自己的def __init__()“替换”.__init__()方法吗?

我读过this另一个SO post,它与我的想法一致,但是得到了相同的堆栈错误。


Tags: path方法runselfqueueinit堆栈def
2条回答

考虑这个简化的例子:

class dog:
    def __init__(self):
        self.legs = 4
        self.sound = 'woof'

class chihuahua(dog):
    def __init__(self):
        self.sound = 'yip'
        # what's missing here?

我们已经创建了dog的子类,名为chihuahua。这个类的用户可以合理地期望它在所有默认方面都像狗一样,除了我们已经覆盖的特定方面(它发出的声音)。但是请注意,正如您所指出的,新的子类__init__替换了基类__init__完全替换。与C++不同,基类初始化代码是在创建子类实例时自动调用的EM>非EEM >。因此,当您创建一个chihuahua()时,self.legs = 4永远不会运行。结果,这种狗到处乱跑,根本不知道它有多少条腿。因此,你可能会争辩说它不是一只功能齐全的狗,而且如果它在试图表演复杂的把戏时摔倒了,你不应该感到惊讶。在

作为子类设计器,您有两个选项来解决此问题。第一个是在子类中显式地重新实现self.legs = 4行。好吧,这在这个例子中可以很好地工作,但一般来说这不是一个很好的选择,因为它违反了DRY原则,即使在您确实知道要编写什么代码以及如何维护它的情况下。在更复杂的例子中(比如你的Thread子类),你大概不知道。第二种选择:显式地调用超类初始值设定项并让它自己去做。在

定义您自己的__init__覆盖基类。但是基__init__为使线程可运行而做的所有工作呢?它通常创建的所有变量和状态都丢失了。除非你把这些都藏在自己身上(为什么要这样做?)当然,这条线是完全无法解开的。在

当然,并不是所有的类都需要__init__,但绝大多数都需要。即使对那些不这样做的人来说,调用__init__也是无害的——它只会转到object.__init__并且在实现者认为__init__是有用的情况下对子类进行验证。在

相关问题 更多 >

    热门问题