⚡IntermediateObject-Oriented Python
Classes and Objects
Defining classes, creating objects, and using instance variables and methods.
Overview
Object-Oriented Programming (OOP) organises code around objects bundles of data (attributes) and behaviour (methods). A class is a blueprint; an object (instance) is a concrete thing created from that blueprint.
In Python every class is defined with the `class` keyword. The special method `__init__` (the constructor) runs automatically when you create a new instance and is where you set up instance variables using `self`.
`self` is a reference to the current instance. Every instance method receives it as its first parameter Python passes it automatically when you call a method on an object. You can name it anything, but `self` is the universal convention.
Class variables are shared across all instances; instance variables (set via `self`) are unique to each object. Understanding this distinction prevents subtle bugs where all instances accidentally share mutable state.
Key Points
- •Define a class with `class Name:`; the constructor is `def __init__(self, ...):`
- •`self` refers to the current instance always the first parameter of instance methods
- •Instance variables: `self.name = value` inside `__init__` unique per object
- •Class variables: defined directly under the class shared by all instances
- •Create an instance: `obj = MyClass(args)` Python calls `__init__` automatically
- •Access attributes: `obj.name`; call methods: `obj.method()`
- •`__str__` controls what `print(obj)` shows always define it for readable output
Examples
Defining a class and creating instances
class Dog:
species = "Canis familiaris" # class variable shared by all dogs
def __init__(self, name, age):
self.name = name # instance variable
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
def __str__(self):
return f"Dog(name={self.name}, age={self.age})"
rex = Dog("Rex", 3)
buddy = Dog("Buddy", 5)
print(rex.bark()) # Rex says: Woof!
print(buddy.name) # Buddy
print(Dog.species) # Canis familiaris
print(rex) # Dog(name=Rex, age=3)Class variables vs instance variables
class Counter:
count = 0 # class variable shared state
def __init__(self, name):
Counter.count += 1
self.name = name
self.id = Counter.count # unique per instance
a = Counter("first")
b = Counter("second")
c = Counter("third")
print(Counter.count) # 3 all instances see this
print(a.id, b.id, c.id) # 1 2 3Use class variables for state shared across all instances, instance variables for per-object state.
Methods that modify state
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit must be positive")
self.balance += amount
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("Insufficient funds")
self.balance -= amount
def __str__(self):
return f"{self.owner}: ${self.balance:.2f}"
acc = BankAccount("Alice", 100)
acc.deposit(50)
acc.withdraw(30)
print(acc) # Alice: $120.00Common Mistakes
- Forgetting `self` as the first parameter of instance methods causes TypeError when calling
- Using a mutable class variable (like a list) instead of setting it in __init__ all instances share the same list
- Calling `obj.__init__()` manually just create a new instance instead
Note
Always define `__str__` for your classes. `print(obj)` will show something useful instead of `<__main__.Dog object at 0x...>`, which makes debugging far easier.
Exercises
Write Python code to solve each exercise. Run it in your browser and check your output.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4