Object Attributes and Methods
Objects have a complete lifecycle: creation (via __init__), active use, and destruction (via __del__). Python calls these special methods automatically.
The Object Lifecycle
An object has a lifecycle with three broad stages. Python creates the object and calls __init__, your program uses the object's attributes and methods, and Python eventually destroys the object. If the class defines __del__, Python calls that method just before destruction.
The important distinction is between active use and final cleanup. While an object is active, your code can access its attributes and call its methods. When Python decides that the object is no longer needed, the object enters its final moment. A defined __del__ method can perform cleanup then, but it cannot prevent the object from being destroyed.
Watching Initialization and Cleanup
class PartyAnimal: def __init__(self, x): self.x = x print("created", self.x) def __del__(self): print("destroyed", self.x) animal = PartyAnimal(7) print("using", animal.x) animal = 42
created 7
using 7
destroyed 7What do you think happens?
What message appears after animal = 42?
Reveal answer
Answer: destroyed 7
The object's x attribute was set to 7 during initialization. Reassigning animal does not change that old object's attribute; it removes the variable's reference to the object, which triggers final cleanup when Python decides the object is no longer needed.
Automatic Special Methods
__init__ and __del__ are special methods that Python calls automatically at important points in an object's lifecycle. __init__ runs when an object is created and gives the class a place to initialize attributes and prepare resources. __del__ runs just before an object is destroyed and gives the class a final opportunity to release resources or perform cleanup.
Other Destruction Triggers
Reassignment is only one common trigger. An object can also become no longer needed when a variable goes out of scope, such as when a function returns and a local variable ceases to exist. A third trigger is program termination: Python destroys remaining objects before the program exits, calling __del__ for objects whose classes define it.
| Situation | What changes | Role of __del__ |
|---|---|---|
| Variable reassignment | The variable is assigned a different value | Provides final cleanup for the old object when Python decides it is no longer needed |
| Variable leaves scope | A local variable ceases to exist after a function returns | Provides final cleanup for the object that is no longer needed |
| Program termination | The program is ending | Provides final cleanup for remaining objects before exit |
Common situations that can lead to object destruction
The key event is not simply that a variable name exists or disappears. The destructor is invoked when Python decides the object is no longer needed. Therefore, trace what happens to the object during reassignment, scope changes, and program termination rather than assuming that __del__ runs immediately after every ordinary operation.
Common Destructor Mistakes
Assuming every class needs a __del__ method.
Python's garbage collector automatically reclaims memory for objects that are no longer in use.
Fix:
Use __del__ when the object manages an external resource that needs final cleanup.Thinking __del__ prevents destruction.
The destructor only provides a final opportunity to perform cleanup; it cannot stop the object from being destroyed.
Fix:
Place the necessary final cleanup in __del__, then allow the object's lifecycle to finish.Expecting __del__ to run while the object is still being used.
__del__ is called just before destruction, not during ordinary active use.
Fix:
Separate normal methods for active work from __del__ for final cleanup.Tracing only the variable name and ignoring the object.
The assignment gives animal a different value; it does not modify the old object's stored x value.
Fix:
Trace the old object's attributes separately from the new value assigned to the variable.
Trace the Lifecycle
Write down the lifecycle sequence for a class that defines both __init__ and __del__. Then identify which event triggers destruction in each case: assigning a new value to the only variable holding the object, returning from a function that created a local object, and reaching the end of the program.
Hints
- Start with object creation and __init__.
- Place ordinary attribute access and method calls during the active-use stage.
- Put __del__ immediately before destruction.
- For each trigger, ask when Python decides that the object is no longer needed.
Tracing one reassignment
A class creates an object with x equal to 12. The only variable holding that object is then assigned a different value. What lifecycle events should be traced?
Creation: Python creates the object and automatically calls __init__, which sets the object's initial attribute x to 12.
Active use: The program can access the object's x attribute and call its methods while the object is active.
Reassignment: The variable is assigned a different value, so it no longer holds the original object.
Final cleanup: Python decides the original object is no longer needed and calls __del__ if the class defines it.
Destruction: After the final cleanup opportunity, Python destroys the original object.
The sequence is creation and __init__, active use, reassignment, __del__, and destruction.
Key Takeaways
- An object's lifecycle moves from creation through active use to destruction.
- __init__ runs automatically during creation and initializes attributes or prepares resources.
- __del__ runs just before destruction when Python decides the object is no longer needed.
- Reassignment, leaving scope, and program termination can lead to destruction.
- Most objects do not need __del__; it is mainly useful for final cleanup of external resources.
Key Takeaways
- Python automatically calls __init__ when an object is created.
- An object remains active while code accesses its attributes and calls its methods.
- Python calls __del__ just before destroying an object when it is no longer needed.
- Reassignment, scope changes, and program termination are common destruction triggers.
- Destructors are uncommon because Python manages memory automatically; they are most useful for external-resource cleanup.