Reputation: 4521
I am trying to understand how to subclass a Thread,
and I am confused with some details of inheritance.
It seems if I want to modify
the __init__
I need to call super as follows:
class MyThread(threading.Thread):
def __init__(self, url, browser, *args, **kwargs):
super(MyThread, self).__init__(*args, **kwargs)
self.url = url
self.browser = browser
This allows me to inherit all of the parents init
attributes as I am using *args, **kwargs
and I can call MyThread._target
within the initializer and it works.
However it seems I don't need to call super to modify the run method. I have seen this example online:
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)
Here it seems they are overwriting the parent init with The threading.Thread.__init__(self
) ?
However, the threading.Thread.__init__(self)
is not
calling any parameters, so it's essentially an empty __init__
and doesn't acquire any of the parents attributes such as target, args, group. If I try to call MyThread._target
I get an error.
So it seems as if they are creating a completely new init
. So why even call threading.Thread.__init__
if you are not going to inherit any
attributes?
And why doesn't run method require the call to the original threading.Thread.run()
if they are modifying the run method?
It seems only init is requiring the call to the original init for modification, but run doesn't require so.
Now another aspect I was confused about was, when I attempted to access the ._target
after super inheritance; the attribute wasn't found in the run method:
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]
Upvotes: 0
Views: 709
Reputation: 532043
The example which calls Thread.__init__
is less general than it could be. Thread.__init__
does, in fact, take some parameters, but they all have default values, so strictly speaking, you don't have to call it with any arguments.
Thread.run
essential does nothing except run the callable passed as the target
option to Thread.__init__
. If you don't pass any such argument, there's no real need to call Thread.run
; the overridden method does all the actual work.
Note that when using super
, it's important to accept and pass on unknown arguments, not so much because you want the Thread
methods to get any required arguments, but because your class doesn't know what class's method might be called next. That is determined by the runtime time of self
, not the subclass of Thread
.
Upvotes: 1