Codectionary / Developer documentation / Python

class

The class keyword defines a blueprint for creating objects in Python. Classes are the foundation of Object-Oriented Programming (OOP), allowing you to bundle data (attributes) and functionality (methods) together. A class defines what attributes an object will have and what operations can be performed on it. Think of a class as a template or a factory for creating objects with similar characteristics.

Syntax

class ClassName:
    def __init__(self, parameters):
        # initialization
    
    def method(self):
        # method body

Examples

Basic Class Definition

Creating a simple class with attributes and methods.

class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def bark(self):
        print(f"{self.name} says Woof!")
    
    def info(self):
        print(f"{self.name} is {self.age} years old")

# Create instances
dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)

# Use methods
dog1.bark()  # Buddy says Woof!
dog2.info()  # Max is 5 years old

Class with Properties

Using properties and encapsulation to control attribute access.

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.__balance = balance  # Private attribute
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            print(f"Deposited ${amount}. New balance: ${self.__balance}")
        else:
            print("Invalid amount")
    
    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            print(f"Withdrew ${amount}. New balance: ${self.__balance}")
        else:
            print("Insufficient funds or invalid amount")
    
    def get_balance(self):
        return self.__balance

account = BankAccount("Alice", 1000)
account.deposit(500)
account.withdraw(200)
print(f"Current balance: ${account.get_balance()}")

Inheritance

Creating child classes that inherit from parent classes.

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        print(f"{self.name} makes a sound")

class Cat(Animal):
    def speak(self):
        print(f"{self.name} says Meow!")

class Bird(Animal):
    def __init__(self, name, can_fly=True):
        super().__init__(name)
        self.can_fly = can_fly
    
    def speak(self):
        print(f"{self.name} says Tweet!")
    
    def fly(self):
        if self.can_fly:
            print(f"{self.name} is flying!")
        else:
            print(f"{self.name} cannot fly")

cat = Cat("Whiskers")
bird = Bird("Tweety")
penguin = Bird("Pingu", can_fly=False)

cat.speak()
bird.speak()
bird.fly()
penguin.fly()

Class Methods and Static Methods

Understanding different types of methods in classes.

class MathOperations:
    pi = 3.14159  # Class attribute
    
    def __init__(self, value):
        self.value = value  # Instance attribute
    
    # Instance method
    def square(self):
        return self.value ** 2
    
    # Class method
    @classmethod
    def circle_area(cls, radius):
        return cls.pi * radius ** 2
    
    # Static method
    @staticmethod
    def add(a, b):
        return a + b

# Instance method usage
math = MathOperations(5)
print(f"Square: {math.square()}")

# Class method usage (no instance needed)
area = MathOperations.circle_area(10)
print(f"Circle area: {area}")

# Static method usage
sum_result = MathOperations.add(3, 7)
print(f"Sum: {sum_result}")

Special Methods (Magic Methods)

Implementing special methods to customize class behavior.

class Book:
    def __init__(self, title, author, pages):
        self.title = title
        self.author = author
        self.pages = pages
    
    # String representation
    def __str__(self):
        return f"{self.title} by {self.author}"
    
    # Detailed representation
    def __repr__(self):
        return f"Book('{self.title}', '{self.author}', {self.pages})"
    
    # Length
    def __len__(self):
        return self.pages
    
    # Comparison
    def __lt__(self, other):
        return self.pages < other.pages
    
    # Addition
    def __add__(self, other):
        return self.pages + other.pages

book1 = Book("Python Basics", "John Doe", 300)
book2 = Book("Advanced Python", "Jane Smith", 450)

print(str(book1))  # Python Basics by John Doe
print(repr(book1)) # Book('Python Basics', 'John Doe', 300)
print(len(book1))  # 300
print(book1 < book2)  # True
print(book1 + book2)  # 750

Real-World Example

A practical class implementation for managing a shopping cart.

class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price

class ShoppingCart:
    def __init__(self):
        self.items = []
    
    def add_item(self, product, quantity=1):
        self.items.append({
            'product': product,
            'quantity': quantity
        })
        print(f"Added {quantity}x {product.name}")
    
    def remove_item(self, product_name):
        self.items = [item for item in self.items 
                     if item['product'].name != product_name]
        print(f"Removed {product_name}")
    
    def get_total(self):
        total = sum(item['product'].price * item['quantity'] 
                   for item in self.items)
        return total
    
    def display_cart(self):
        if not self.items:
            print("Cart is empty")
            return
        
        print("\n=== Shopping Cart ===")
        for item in self.items:
            p = item['product']
            q = item['quantity']
            subtotal = p.price * q
            print(f"{p.name} x{q} - ${subtotal:.2f}")
        print(f"Total: ${self.get_total():.2f}\n")

# Usage
cart = ShoppingCart()

laptop = Product("Laptop", 999.99)
mouse = Product("Mouse", 29.99)

cart.add_item(laptop, 1)
cart.add_item(mouse, 2)
cart.display_cart()

cart.remove_item("Mouse")
cart.display_cart()

Best practices

  • Use PascalCase for class names (MyClass, not my_class or myclass)
  • Always define __init__ method to initialize instance attributes
  • Use self as the first parameter name in instance methods (convention)
  • Implement __str__ and __repr__ methods for better debugging and printing
  • Use properties (@property) for computed attributes and validation
  • Keep classes focused on a single responsibility - don't make "god objects"
  • Document your classes with docstrings explaining their purpose and usage
  • Use private attributes (prefix with __) when you want to prevent direct access

At a glance

Purpose
Scripting and general-purpose applications
File extension
.py
Runs in
Python interpreter
Usually used with
Python standard library and packages

Specifications & further reading

Related Python documentation

Inheritance & super()
Inheritance lets a class (the child or subclass) reuse and extend the attributes and methods of another class (the parent or superclass), written as class Child(Parent). The built-in super() function gives access to the parent class's methods from within the child, most commonly used to call the parent's __init__ so the child doesn't have to duplicate its setup logic. Python also supports multiple inheritance, where a class inherits from more than one parent.
Magic (Dunder) Methods
Magic methods, also called dunder (double underscore) methods, let your custom classes hook into Python's built-in syntax and behavior. __init__ runs on object creation, __str__ controls how an object is displayed with print(), __eq__ and __lt__ control comparisons, __len__ controls the len() function, and __add__ lets objects respond to the + operator. Implementing these makes your custom classes feel like natural, first-class Python types.
@property
The @property decorator lets you define a method that can be accessed like a plain attribute, without parentheses. This is useful for computed values that should look like simple attributes, and for adding validation logic that runs whenever an attribute is set, via a matching @x.setter. Properties let you start with simple public attributes and later add logic without breaking any code that uses the class.
@staticmethod and @classmethod
Regular instance methods automatically receive self, the specific object they were called on. @staticmethod methods receive neither self nor the class - they behave like a plain function that just happens to live inside a class, grouped there for organizational purposes. @classmethod methods receive the class itself (conventionally named cls) instead of an instance, making them useful for alternative constructors that build an instance in a different way.