Python Tutorial / Group State and Behavior with Classes and Instances
A class defines related data and behavior; an instance is an individual object created from that definition. Use classes when state and its rules belong together, rather than converting every simple calculation into an object.
Relate the definition to individual objects
The same Expense class can create independent lunch and bus records. Each has its own name and amount while using the methods defined by the class. self is the conventional parameter receiving the instance on which a method is called.
__init__ initializes an object after creation. Do not supply self explicitly in an ordinary bound-method call. The location where an attribute is stored determines whether it belongs to one instance or is shared.
For the relevant APIs and platform requirements, see Python: classes.
Instance attributes and access rules build on the rules demonstrated in Distinguish Instance Attributes from Class Attributes.
Run two expense instances
Save the complete code below as classes_demo.py in a separate practice folder, using UTF-8. Run python classes_demo.py in a terminal with your project virtual environment selected. Outside a virtual environment on macOS or Ubuntu, use python3 when that is your interpreter command.
class Expense:
def __init__(self, name, amount):
if amount < 0:
raise ValueError("negative amount")
self.name = name
self.amount = amount
def describe(self):
return f"{self.name}: {self.amount:,} KRW"
first = Expense("lunch", 8000)
second = Expense("bus", 2500)
print(first.describe())
print(second.describe())
print(first.amount + second.amount)
Expected output:
lunch: 8,000 KRW bus: 2,500 KRW 10500
Keep each object’s responsibility focused
The initializer checks that an amount is nonnegative. Accepting strings, bool or fractional amounts would require an additional contract. Directly assigning first.amount afterwards can still bypass that initial check, so initialization alone does not control every state change.
Putting display, file storage and network transmission into Expense can make it difficult to reuse and test. Separate the record’s rules from external persistence and provide required collaborators explicitly.
self refers to the instance receiving the method call. Two instances of one class can hold different instance attributes. Read the relationship table as name → object → its attributes; this makes the receiver of each method call explicit.
| Name | Distinct object | Instance attribute |
|---|---|---|
| first | object A | first.amount = 3500 |
| second | object B | second.amount = 8000 |
first and second are illustrative names in this relationship table. Changing one instance attribute does not change the other instance’s attribute.
Check independence and the chosen abstraction
- Set first.amount to 9000 and verify that second.amount stays 2500.
- Construct an instance with -1 and observe ValueError.
- Explain why Expense.describe(first) and first.describe() produce the same description.
An attribute typo can create an unintended attribute instead of changing the intended field. Dataclasses, type hints and tests can make larger records clearer, but each solves a different problem. The property lesson shows one way to enforce a rule on subsequent assignments.




