与子线程类和继承的混淆

时间:2019-04-07 20:26:12

标签: python multithreading oop inheritance subclassing

我试图了解如何对Thread进行子类化, 而且我对继承的一些细节感到困惑。 好像我要修改 __init__我需要按以下方式调用super:

class MyThread(threading.Thread):
    def __init__(self, url, browser, *args, **kwargs):
        super(MyThread, self).__init__(*args, **kwargs)
        self.url = url
        self.browser = browser

这使我可以继承所有父母init 属性,就像我正在使用*args, **kwargs一样,我可以在初始化器中调用MyThread._target,并且可以正常工作。

但是,我似乎不需要调用super来 修改运行方法。我在网上看到了这个例子:

class MyThread(threading.Thread):

    def __init__(self, number, logger):
        threading.Thread.__init__(self)
        self.number = number
        self.logger = logger

    def run(self):
        """
        Run the thread
        """
        #modification to run method but no call to it
        logger.debug('Calling doubler')
        doubler(self.number, self.logger)

在这里似乎他们正在用threading.Thread.__init__(self覆盖父init? 但是,threading.Thread.__init__(self)不是 调用任何参数,因此它本质上是一个空__init__,并且不会获取任何父属性,例如target,args,group。如果我尝试致电MyThread._target,则会收到错误消息。 因此,似乎他们正在创建全新的init。那么,如果您不继承任何内容,为什么还要致电threading.Thread.__init__ 属性?

如果运行方法正在修改运行方法,为什么不要求调用原始threading.Thread.run()? 似乎只有init才需要调用原始init进行修改,但run并不需要。

现在让我感到困惑的另一个方面是,当我尝试在超级继承之后访问._target时;在run方法中找不到该属性:

class MyThread(threading.Thread):
    def __init__(self, number, style, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.number = number
        self.style = style
        print(self._target) # works here

    def run(self, *args, **kwargs):
        super().run(*args, **kwargs)
        print(self._target) # leads to error
        print('thread has ended')




custom = MyThread(target = print, number = 3, style ="red", args = ("test",))
custom.run()

输出:

<built-in function print>
test

Traceback:
custom.run()...........
print(self._target)
AttributeError: 'MyThread' object has no attribute '_target'[/python]

这些就是我很困惑的事情,希望有人能澄清这些细节。

谢谢。

1 个答案:

答案 0 :(得分:1)

调用Thread.__init__的示例不那么通用。 Thread.__init__实际上有一些参数,但是它们都有默认值,因此严格来说,您没有拥有可以使用任何参数来调用它。

Thread.run必需的内容什么都不做,除了运行通过target选项传递给Thread.__init__的可调用对象。如果您不传递任何此类参数,则无需真正调用Thread.run;覆盖的方法可以完成所有实际工作。

请注意,在使用super时,接受并传递未知参数很重要,不是那么重要,因为您希望Thread方法获取任何必需的参数,但因为您的类不会< em>知道下一步将调用什么类的方法。这取决于self的运行时间,而不是Thread的子类。