我试图理解如何子类化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
这允许我继承所有父类初始化属性,因为我正在使用*args, **kwargs
,我可以在初始化程序中调用MyThread._target
并且它可以工作。
但是,似乎我不需要调用super来修改run方法。我在网上看过这个例子:
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()
,如果他们正在修改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()
OUTPUT:
<built-in function print>
test
Traceback:
custom.run()...........
print(self._target)
AttributeError: 'MyThread' object has no attribute '_target'[/python]
所以这些是我感到困惑的事情,我希望有人可以澄清这些细节。
谢谢。
调用Thread.__init__
的例子不太常见。事实上,Thread.__init__
确实采用了一些参数,但它们都有默认值,所以严格来说,你不必用任何参数调用它。
Thread.run
必不可少,除了运行target
选项传递给Thread.__init__
的callable。如果你没有传递任何这样的论点,那么就没有必要打电话给Thread.run
;重写的方法完成所有实际工作。
请注意,在使用super
时,接受并传递未知参数非常重要,而不是因为您希望Thread
方法获取任何必需的参数,而是因为您的类不知道接下来可能调用哪个类的方法。这是由self
的运行时间决定的,而不是Thread
的子类。