How do you make a new object ready to use? Define __init__ to give each instance its initial attributes. Calling a class, such as Task(...), triggers initialization; you do not normally call __init__ yourself. section 8.1 section 8.1.2
Initialize a task
class Task: def __init__(self, title, desc, urgency): self.title = title self.desc = desc self.urgency = urgency self.status = "created" self.tags = [] task = Task("Laundry", "Wash clothes", 3) print(task.__dict__) # {'title': 'Laundry', 'desc': 'Wash clothes', 'urgency': 3, # 'status': 'created', 'tags': []} The constructor arguments supply essential data. The other attributes receive useful initial values, so code can inspect status or add a tag immediately. section 8.1.2 section 8.1.3
Keep initialization predictable:
- Put __init__ first among the class’s methods and declare all instance attributes there. Creating an attribute only in a later method can cause AttributeError before that method runs. section 8.1.3 section 8.1.5
- Use self as the first parameter. It refers to the new instance and is supplied implicitly when you call the class. The name is conventional, not a Python keyword. section 8.1.1
- Choose required arguments for essential attributes. Optional values can have defaults, but defaulted parameters must follow required ones. Take care when considering a mutable default such as a list. section 8.1.2 section 9.2.2
Figure 8.1 The detailed instantiation process behind the scenes. When you create an instance object by calling the constructor, the instance object is created first by the __new__ method. When it’s created, it’s sent to the __init__ method to complete the initialization, where the instance’s attributes are set.
The instantiation diagram separates two jobs: __new__ creates the object, then __init__ receives that same object as self and initializes it. Custom classes typically need __init__, not a custom __new__. section 8.1.1 section 10.2.1
If a subclass needs different initial state, override __init__ and use super() for the superclass’s initialization; otherwise, inherit its implementation. For repetitive data-holder classes, @dataclass can generate __init__ from annotated fields instead. section 8.5.6 section 9.2.2 section 9.2.1












