Classes and Objects

The foundation of everything. A class is the blueprint, an object is the instance.

class Vehicle:
    def __init__(self, make, model):
        self.make = make
        self.model = model

    def describe(self):
        return f"{self.make} {self.model}"

car = Vehicle("Toyota", "Camry")
print(car.describe())

Instance vs Class vs Static Variables and Methods

class Counter:
    count = 0  # class variable, shared across all instances

    def __init__(self, name):
        self.name = name  # instance variable, unique per object
        Counter.count += 1

    def getName(self):  # instance method, operates on self
        return self.name

    @classmethod
    def getCount(cls):  # class method, operates on the class itself
        return cls.count

    @staticmethod
    def description():  # static method, no access to class or instance
        return "A simple counter class"

Instance methods take self. Class methods take cls and are called on the class. Static methods are essentially namespaced functions with no implicit reference to anything.


Encapsulation

Bundling data and the methods that operate on it together, and controlling access to internals.

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # private: name-mangled to _BankAccount__balance

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def getBalance(self):
        return self.__balance

Python does not enforce true privacy. The convention is:


Inheritance

A subclass inherits attributes and methods from a parent class and can extend or override them.

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "..."

class Dog(Animal):
    def speak(self):  # overrides parent method
        return "Woof"

class Cat(Animal):
    def speak(self):
        return "Meow"

dog = Dog("Rex")
print(dog.speak())   # Woof
print(dog.name)      # Rex, inherited from Animal

super()