Basic class definition: blueprint for creating objects
class Person: # Class definition with class name
def __init__(self, name, age): # Constructor method: called when creating new instance
self.name = name # Instance attribute: unique to each object
self.age = age # Instance attribute: unique to each object
def greet(self): # Instance method: behavior of the object
return f"Hello, my name is {self.name}" # Use instance attribute in method
Creating an instance (object) of the Person class
person = Person("Alice", 30) # Instantiate with arguments for constructor
print(person.greet()) # Call instance method: "Hello, my name is Alice"
Class with method chaining: methods return self for fluent interface
class Calculator: # Calculator class for mathematical operations
def __init__(self):
self.result = 0 # Initialize result to zero
def add(self, x): # Method to add value to result
self.result += x # Modify instance attribute
return self # Return self for method chaining
def subtract(self, x): # Method to subtract value from result
self.result -= x # Modify instance attribute
return self # Return self for method chaining
def get_result(self): # Method to retrieve current result
return self.result # Return the current value
Using method chaining for fluent interface
calc = Calculator() # Create calculator instance
result = calc.add(5).subtract(2).get_result() # Chain method calls
print(result) # Output: 3
Class attributes: shared by all instances of the class
class Dog: # Dog class with both class and instance attributes
species = "Canis familiaris" # Class attribute: shared by all Dog instances
def __init__(self, name, age):
self.name = name # Instance attribute: unique to each Dog object
self.age = age # Instance attribute: unique to each Dog object
Creating multiple instances of the Dog class
dog1 = Dog("Buddy", 3) # First dog instance
dog2 = Dog("Max", 5) # Second dog instance
Accessing class attribute (same for all instances)
print(dog1.species) # Output: Canis familiaris
print(dog2.species) # Output: Canis familiaris
print(Dog.species) # Output: Canis familiaris (access via class)
Instance attributes: unique to each object instance
class Car: # Car class with instance attributes and methods
def __init__(self, brand, model, year):
self.brand = brand # Instance attribute: car brand
self.model = model # Instance attribute: car model
self.year = year # Instance attribute: manufacturing year
self.is_running = False # Instance attribute: default state (not running)
def start(self): # Method to start the car
self.is_running = True # Modify instance attribute
def stop(self): # Method to stop the car
self.is_running = False # Modify instance attribute
Creating and using a Car instance
car = Car("Toyota", "Camry", 2020) # Create car instance
car.start() # Call method to start car
print(car.is_running) # Output: True (car is now running)
class Animal: # Parent/base class
def __init__(self, name):
self.name = name # Common attribute for all animals
def speak(self): # Abstract method (placeholder)
pass # Base implementation (does nothing)class Dog(Animal): # Child class inherits from Animal
def speak(self): # Override parent method with specific implementation
return f"{self.name} says Woof!" # Dog-specific behavior
class Cat(Animal): # Child class inherits from Animal
def speak(self): # Override parent method with specific implementation
return f"{self.name} says Meow!" # Cat-specific behavior
Creating instances of child classes
dog = Dog("Buddy") # Dog inherits __init__ from Animal
cat = Cat("Whiskers") # Cat inherits __init__ from Animal
Demonstrating polymorphic behavior
print(dog.speak()) # Output: Buddy says Woof!
print(cat.speak()) # Output: Whiskers says Meow!
Multiple inheritance: class inherits from multiple parent classes
class Flyable: # First parent class (mixin)
def fly(self):
return "I can fly!" # Method from first parentclass Swimmable: # Second parent class (mixin)
def swim(self):
return "I can swim!" # Method from second parent
class Duck(Flyable, Swimmable): # Child inherits from both parents
def __init__(self, name):
self.name = name # Duck-specific attribute
def speak(self):
return f"{self.name} says Quack!" # Duck-specific method
Creating instance that inherits from multiple classes
duck = Duck("Donald") # Duck has methods from both Flyable and Swimmable
print(duck.fly()) # Output: I can fly! (from Flyable)
print(duck.swim()) # Output: I can swim! (from Swimmable)
print(duck.speak()) # Output: Donald says Quack! (from Duck)
Method Resolution Order (MRO): determines which method to call in multiple inheritance
class A: # Base class
def method(self):
return "A" # Base method implementationclass B(A): # Inherits from A
def method(self):
return "B" # Override A's method
class C(A): # Also inherits from A
def method(self):
return "C" # Override A's methodclass D(B, C): # Inherits from both B and C (B comes first)
pass # No method override, uses B's method
Demonstrating MRO behavior
d = D() # Create instance of D
print(d.method()) # Output: B (B's method wins due to MRO)
print(D.__mro__) # Shows method resolution order: (D, B, C, A, object)
Encapsulation: protecting data with private attributes and public methods
class BankAccount: # Bank account with encapsulated balance
def __init__(self, balance):
self.__balance = balance # Private attribute: cannot be accessed directly
def get_balance(self): # Public method: safe way to access balance
return self.__balance # Return private attribute value
def deposit(self, amount): # Public method: safe way to modify balance
if amount > 0: # Validation: only positive amounts allowed
self.__balance += amount # Modify private attribute
return True # Return success status
return False # Return failure status
def withdraw(self, amount): # Public method: safe way to modify balance
if 0 < amount <= self.__balance: # Validation: amount must be positive and available
self.__balance -= amount # Modify private attribute
return True # Return success status
return False # Return failure status
Using encapsulated bank account
account = BankAccount(1000) # Create account with initial balance
print(account.get_balance()) # Output: 1000 (safe access)
account.deposit(500) # Safe modification through method
print(account.get_balance()) # Output: 1500 (balance increased)
print(account.__balance) # AttributeError: private attribute not accessible
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
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):
import math
return math.pi * self._radius ** 2circle = Circle(5)
print(circle.radius) # 5
print(circle.area) # 78.54...
circle.radius = 10
print(circle.area) # 314.16...
class Shape:
def area(self):
passclass Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * self.radius ** 2shapes = [Rectangle(4, 5), Circle(3)]
for shape in shapes:
print(f"Area: {shape.area()}")
class Duck:
def swim(self):
return "Duck swimming"
def fly(self):
return "Duck flying"class Airplane:
def fly(self):
return "Airplane flying"
def make_it_fly(flying_object):
return flying_object.fly()duck = Duck()
airplane = Airplane()
print(make_it_fly(duck)) # Duck flying
print(make_it_fly(airplane)) # Airplane flying
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"Point({self.x}, {self.y})"
def __repr__(self):
return f"Point({self.x}, {self.y})"
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1) # Point(1, 2)
print(p1 == p2) # False
print(p1 + p2) # Point(4, 6)
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file:
self.file.close()
Using the context manager
with FileManager("test.txt", "w") as f:
f.write("Hello, World!")
from abc import ABC, abstractmethodclass Animal(ABC):
@abstractmethod
def speak(self):
pass
@abstractmethod
def move(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
def move(self):
return "Running on four legs"
animal = Animal() # TypeError: Can't instantiate abstract class
dog = Dog()
print(dog.speak()) # Woof!
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_string):
year, month, day = map(int, date_string.split('-'))
return cls(year, month, day)
def __str__(self):
return f"{self.year}-{self.month:02d}-{self.day:02d}"date = Date.from_string("2023-12-25")
print(date) # 2023-12-25
class MathUtils:
@staticmethod
def add(x, y):
return x + y
@staticmethod
def multiply(x, y):
return x * y
@staticmethod
def is_even(n):
return n % 2 == 0print(MathUtils.add(5, 3)) # 8
print(MathUtils.is_even(4)) # True
class Meta(type):
def __new__(cls, name, bases, attrs):
# Add a class attribute to all classes created with this metaclass
attrs['created_by'] = 'Meta'
return super().__new__(cls, name, bases, attrs)class MyClass(metaclass=Meta):
pass
print(MyClass.created_by) # Meta
---
Previous Chapter | Next Chapter