Classes let you bundle data and behavior. Here is how to use them effectively.

Basic Class

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
    
    def greet(self):
        return f"Hello, I am {self.name}"
 
user = User("Owen", "owen@example.com")
print(user.name)
print(user.greet())

Instance Attributes

class Counter:
    def __init__(self, start=0):
        self.count = start
    
    def increment(self):
        self.count += 1
        return self.count
 
c = Counter(10)
c.increment()

Class vs Instance Attributes

class Dog:
    species = "Canis familiaris"  # Class attribute
    
    def __init__(self, name):
        self.name = name  # Instance attribute
 
dog1 = Dog("Rex")
dog2 = Dog("Buddy")

Inheritance

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        raise NotImplementedError
 
class Dog(Animal):
    def speak(self):
        return f"{self.name} says woof!"

Using super

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

Properties

class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    def get_radius(self):
        return self._radius
    
    def set_radius(self, value):
        if value < 0:
            raise ValueError("Radius must be positive")
        self._radius = value

Use the property decorator for cleaner syntax.

Special Methods

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
 
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)

Common Special Methods

  • __init__: Constructor
  • __repr__: Developer representation
  • __str__: User representation
  • __eq__: Equality
  • __add__: Addition
  • __len__: Length

Class Methods

class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

Use classmethod decorator for alternative constructors.

Static Methods

Static methods are utility functions that do not need instance or class access.

Abstract Classes

Use the abc module to define abstract base classes that cannot be instantiated directly.

Composition vs Inheritance

Inheritance means "is a" relationship. Composition means "has a" relationship.

Prefer composition when possible. It is more flexible.

When to Use Classes

Use classes when you have data with associated behavior and need multiple instances.

Use functions when you just need to transform data with no state.

Use dataclasses when you mainly need a data container with less boilerplate.

Do not force OOP. Use it when it simplifies your code.

React to this post: