Advanced
Object-Oriented Programming
Learn to design classes, use inheritance and polymorphism, encapsulate data, and leverage Python's special methods and properties.
Classes and Objects
A class is a blueprint for creating objects. An object is an instance of a class.
Python
class Dog: """A simple Dog class.""" species = "Canis familiaris" # Class attribute def __init__(self, name, age): """Initialize a new Dog.""" self.name = name # Instance attribute self.age = age # Instance attribute def bark(self): return f"{self.name} says Woof!" def info(self): return f"{self.name} is {self.age} years old" # Create objects (instances) buddy = Dog("Buddy", 3) max_dog = Dog("Max", 5) print(buddy.bark()) # Buddy says Woof! print(max_dog.info()) # Max is 5 years old print(Dog.species) # Canis familiaris
Class Methods and Static Methods
Python
class Employee: raise_rate = 1.04 count = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.count += 1 # Instance method def apply_raise(self): self.salary *= self.raise_rate # Class method - works with the class, not instances @classmethod def set_raise_rate(cls, rate): cls.raise_rate = rate # Class method as alternative constructor @classmethod def from_string(cls, emp_str): name, salary = emp_str.split("-") return cls(name, int(salary)) # Static method - utility, no access to cls or self @staticmethod def is_workday(day): return day.weekday() < 5 emp = Employee.from_string("Alice-75000")
Inheritance
Python
class Animal: def __init__(self, name): self.name = name def speak(self): raise NotImplementedError("Subclass must implement") class Cat(Animal): def speak(self): return f"{self.name} says Meow!" class Dog(Animal): def __init__(self, name, breed): super().__init__(name) # Call parent's __init__ self.breed = breed def speak(self): return f"{self.name} says Woof!" cat = Cat("Whiskers") dog = Dog("Rex", "Labrador") print(cat.speak()) # Whiskers says Meow! print(dog.speak()) # Rex says Woof!
Polymorphism
Python
# Same interface, different behavior animals = [Cat("Whiskers"), Dog("Rex", "Lab"), Cat("Tom")] for animal in animals: print(animal.speak()) # Each calls its own version
Encapsulation
Python
class BankAccount: def __init__(self, owner, balance=0): self.owner = owner # Public self._balance = balance # Protected (convention) self.__pin = "1234" # Private (name mangling) def deposit(self, amount): if amount > 0: self._balance += amount return True return False def get_balance(self): return self._balance acct = BankAccount("Alice", 1000) acct.deposit(500) print(acct.get_balance()) # 1500
Magic Methods (Dunder Methods)
Python
class Vector: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Vector({self.x}, {self.y})" def __str__(self): return f"({self.x}, {self.y})" def __len__(self): return int((self.x**2 + self.y**2)**0.5) def __add__(self, other): return Vector(self.x + other.x, self.y + other.y) def __eq__(self, other): return self.x == other.x and self.y == other.y v1 = Vector(3, 4) v2 = Vector(1, 2) print(v1 + v2) # (4, 6) print(repr(v1)) # Vector(3, 4) print(len(v1)) # 5
Properties (@property)
Python
class Circle: def __init__(self, radius): self._radius = radius @property def radius(self): """Get the radius.""" return self._radius @radius.setter def radius(self, value): if value < 0: raise ValueError("Radius cannot be negative") self._radius = value @property def area(self): """Computed property.""" import math return math.pi * self._radius ** 2 c = Circle(5) print(c.radius) # 5 (uses getter) print(c.area) # 78.54 (computed) c.radius = 10 # Uses setter with validation
When to use OOP: Use classes when you have data and behavior that belong together, need multiple instances with shared behavior, or want to model real-world entities. For simple scripts, functions alone are often sufficient.
Lilly Tech Systems