Your __init__ method is entirely redundant. You are in effect replacing Thread.__init__() with your own implementation, where your own implementation simply calls Thread.__init__(). If you removed it, nothing would change:

class Example(Thread):
    def run (self):
        print("It works!")

Your Example.run() method is simply called because you started the thread using the Thread.start() method:

start()
Start the thread’s activity.

It must be called at most once per thread object. It arranges for the object’s run() method to be invoked in a separate thread of control.

Also see the Thread.run() documentation:

run()
Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

Your __init__ method had nothing to do with that.

Now, if you created a __init__ method in a Thread subclass and then did not make sure Thread.__init__ was called, then you prevented the class from setting important instance information, breaking instances:

>>> from threading import Thread
>>> class Example(Thread):
...     def run (self):
...         print("It works!")
... 
>>> Example().start()
It works!

>>> class BrokenExample(Thread):
...     def __init__(self):
...         # not doing anything
...         pass
...     def run (self):
...         print("It works!")
... 
>>> BrokenExample().start()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python2.7/threading.py", line 737, in start
    raise RuntimeError("thread.__init__() not called")
RuntimeError: thread.__init__() not called

Because this is a common error to make, the Thread.start method throws a custom exception to tell you explicitly that Thread.__init__ was not executed.

Answer from Martijn Pieters on Stack Overflow
Top answer
1 of 2
10

Your __init__ method is entirely redundant. You are in effect replacing Thread.__init__() with your own implementation, where your own implementation simply calls Thread.__init__(). If you removed it, nothing would change:

class Example(Thread):
    def run (self):
        print("It works!")

Your Example.run() method is simply called because you started the thread using the Thread.start() method:

start()
Start the thread’s activity.

It must be called at most once per thread object. It arranges for the object’s run() method to be invoked in a separate thread of control.

Also see the Thread.run() documentation:

run()
Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

Your __init__ method had nothing to do with that.

Now, if you created a __init__ method in a Thread subclass and then did not make sure Thread.__init__ was called, then you prevented the class from setting important instance information, breaking instances:

>>> from threading import Thread
>>> class Example(Thread):
...     def run (self):
...         print("It works!")
... 
>>> Example().start()
It works!

>>> class BrokenExample(Thread):
...     def __init__(self):
...         # not doing anything
...         pass
...     def run (self):
...         print("It works!")
... 
>>> BrokenExample().start()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python2.7/threading.py", line 737, in start
    raise RuntimeError("thread.__init__() not called")
RuntimeError: thread.__init__() not called

Because this is a common error to make, the Thread.start method throws a custom exception to tell you explicitly that Thread.__init__ was not executed.

2 of 2
2

__init__() method is called when an object is initialized. And when you do - Thread.__init__(self) , it just just calling the parent class' __init__() method .

Like said in comment you can remove it and the functionality should remain same. In your class the __init__() is completely redundant.

This method is called when you do -

Example()

When you create the new object for Example() .

The run() method is called, when you do - .start() on the Example() object. This is done by the Thread.start() method, from documentation -

start()

Start the thread’s activity.

It must be called at most once per thread object. It arranges for the object’s run() method to be invoked in a separate thread of control.


Adding one more print statement and dividing Example().start() into two lines so you can understand this clearly -

>>> from threading import Thread
>>> class Example(Thread):
...     def __init__(self):
...         Thread.__init__(self)
...         print("In __init__")
...     def run (self):
...         print("It's working!")
...
>>> e = Example()
In __init__
>>> e.start()
It's working!
🌐
Python
docs.python.org › 3 › library › threading.html
threading — Thread-based parallelism — Python 3.14.3 ...
For that reason, you generally don’t want to save these values across threads, as they apply only to the thread they came from. You can create custom local objects by subclassing the local class: >>> class MyLocal(local): ... number = 2 ... def __init__(self, /, **kw): ...
🌐
Real Python
realpython.com › intro-to-python-threading
An Intro to Threading in Python – Real Python
August 5, 2024 - If one thread gets the lock but never gives it back, your program will be stuck. You’ll read more about this later. Fortunately, Python’s Lock will also operate as a context manager, so you can use it in a with statement, and it gets released automatically when the with block exits for any reason. Let’s look at the FakeDatabase with a Lock added to it. The calling function stays the same: ... class FakeDatabase: def __init__(self): self.value = 0 self._lock = threading.Lock() def locked_update(self, name): logging.info("Thread %s: starting update", name) logging.debug("Thread %s about to
🌐
Bogotobogo
bogotobogo.com › python › Multithread › python_multithreading_subclassing_creating_threads.php
Python Multithreading Tutorial: Subclassing Thread - 2020
No other methods (except for the constructor) should be overridden in a subclass. In other words, we only override the __init__() and run() methods of a class. In this section, we will create a subclass of Thread and override run() to do whatever is necessary:
🌐
Python
docs.python.org › 2.0 › lib › thread-objects.html
7.5.6 Thread Objects
If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.
🌐
Python
docs.python.org › 3 › c-api › init.html
Initialization, finalization, and threads — Python 3.14.3 documentation
This page has been split up into the following: Interpreter initialization and finalization, Thread states and the global interpreter lock, Synchronization primitives, Thread-local storage support,...
🌐
Python 101
python101.pythonlibrary.org › chapter21_thread.html
Chapter 21 - The threading module — Python 101 1.0 documentation
# Python 2 version import os import urllib2 from threading import Thread class DownloadThread(Thread): """ A threading example that can download a file """ def __init__(self, url, name): """Initialize the thread""" Thread.__init__(self) self.name = name self.url = url def run(self): """Run the thread""" handle = urllib2.urlopen(self.url) fname = os.path.basename(self.url) with open(fname, "wb") as f_handler: while True: chunk = handle.read(1024) if not chunk: break f_handler.write(chunk) msg = "%s has finished downloading %s!" % (self.name, self.url) print(msg) def main(urls): """ Run the prog
🌐
GeeksforGeeks
geeksforgeeks.org › how-to-create-a-new-thread-in-python
How to create a new thread in Python - GeeksforGeeks
September 30, 2021 - Then we override the __init__ function of the thread class. Then we override the run method to define the behavior of the thread. The start() method starts a Python thread.
Find elsewhere
🌐
Python Module of the Week
pymotw.com › 2 › threading
threading – Manage concurrent threads - Python Module of the Week
__init__() is invoked on the same object (note the id() value), once in each thread. $ python threading_local_defaults.py (MainThread) Initializing <__main__.MyLocal object at 0x100514390> (MainThread) value=1000 (Thread-1 ) Initializing <__main__.MyLocal object at 0x100514390> (Thread-1 ) value=1000 (Thread-2 ) Initializing <__main__.MyLocal object at 0x100514390> (Thread-1 ) value=81 (Thread-2 ) value=1000 (Thread-2 ) value=54
Top answer
1 of 2
2

Consider this simplified example:

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

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

We've created a subclass of dog, called chihuahua. A user of this class would reasonably expect it to behave like a dog in all default aspects, except the specific one that we have overridden (the sound it makes). But note that, as you have pointed out, the new subclass __init__ replaces the base class __init__. Completely replaces. Unlike C++, the base-class initialization code is not automatically called when a subclass instance is created. Therefore, the line self.legs = 4 never gets run when you create a chihuahua(). As a result, this type of dog is running around without any idea how many legs it has. Hence you could argue it is not a fully-functioning dog, and you shouldn't be surprised if it falls over while trying to perform complex tricks.

As subclass designer you have two options to fix this. The first is to reimplement the self.legs = 4 line explicitly in the subclass. Well, that'll work fine in this example, but it's not a great option in general because it violates the DRY principle even in cases where you do know exactly what code to write and how to maintain it. And in more complex examples (like your Thread subclass), you presumably won't know. Second option: explicitly call the superclass initializer and let it do its thing.

2 of 2
1

Defining your own __init__ overrides the base class. But what about all the work the base __init__ does to make the thread runnable? All variables and state that it would normally create are missing. Unless you hack all of that in yourself (and why do that?) the thread is of course completely unrunnable.

Not all classes need an __init__ of course, but the vast majority do. Even for the ones that don't, calling __init__ is harmless - it just goes to object.__init__ and future-proofs the child class in the event an implementer decides an __init__ is useful after all.

🌐
Python Central
pythoncentral.io › how-to-create-a-thread-in-python
How to Create a Thread in Python | Python Central
May 8, 2013 - [python] class MyThread(Thread): def __init__(self, val): ''' Constructor.
🌐
Python Forum
python-forum.io › thread-17340.html
Confusion with sublcassing a threading class, and inheritance
April 7, 2019 - 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, brow...
🌐
thisPointer
thispointer.com › home › python › create a thread using class in python
Create a Thread using Class in Python - thisPointer
February 16, 2019 - In class FileLoaderThread’s constructor (__init__() ) we have called the base class (Thread) __init__() function without any arguments and stored the passed arguments in it’s member variables.
🌐
Nitratine
nitratine.net › blog › post › python-threading-basics
Python Threading Basics - Nitratine
May 3, 2018 - To create the threads, we first initialise a threading.Thread instance passing the method as the target. We then add this thread to our previously create list and start it. This will provide the following output: $ python threading_method.py Hello World Hello World Hello World Hello World
🌐
Tutorialspoint
tutorialspoint.com › python › python_multithreading.htm
Python - Multithreading
To create and start a new thread in Python, you can use either the low-level _thread module or the higher-level threading module. The threading module is generally recommended due to its additional features and ease of use.
🌐
Python
docs.python.org › 3.4 › library › threading.html
17.1. threading — Thread-based parallelism — Python 3.4.10 documentation
June 16, 2019 - The Thread class represents an activity that is run in a separate thread of control. There are two ways to specify the activity: by passing a callable object to the constructor, or by overriding the run() method in a subclass. No other methods (except for the constructor) should be overridden in a subclass. In other words, only override the __init__() and run() methods of this class.
🌐
GitHub
github.com › python › cpython › issues › 115121
AssertionError: Thread.__init__() not called · Issue #115121 · python/cpython
February 7, 2024 - This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False. The entire Python program exits when only daemon threads are left.
Author   wilson3q
🌐
Stack Overflow
stackoverflow.com › questions › 53197675 › thread-and-init-at-the-same-time-how-it-works
python - Thread and init at the same time (how it works?) - Stack Overflow
This is because you override the original Thread.__init__(), which handles name as you would expect. The default names for the threads are Thread-1 and so on, in the respective order they are created.