There are objects in the real world (phone, microphone, popcorn). Objects have attributes (what it is or has; properties) and methods (what it can do). In Python, a class can be used to create an object. A class is a blueprint or template that describes what attributes and methods an object has.
Class: data type, such as int
, string
, function
, or user-defined Car
Object: instantiated class
Method: a function encapsulated within a class, such as the string
class .upper()
method.
Encapsulation: is where data in a class are hidden from other classes and only accessible via the class’s methods (‘data-hiding’); Objects (e.g. Cat) manage their own state/attributes (e.g., energy, age), have private methods (e.g., .meow(), .sleep()) that they can call whenever they want, and can only be touched by other classes via public methods (e.g., .feed()).
Abstraction means exposing only the high-level mechanisms relevant to other objects and hiding internal implementation.
Inheritance through class hierarchy, with each child class reusing common logic from parent classes and adding only what is necessary.
Polymorphism is where an object possesses different behaviours in different situations.
Some additional points (source):
- Classes hide implementation detail from users, enabling implementation to be changed without affecting users.
- Look to use consistent methods in a group of related classes, so that you can switch between them without affecting the code using it. Consider Python ‘duck typing’ ("if it looks/talks like a duck..." or abstract classes and methods.
- Be aware of trading maintainability for complexity - one large class or too many classes can be hard to understand.
- Prefer encapsulation over inheritance, especially with code reuse.
- For an immutable class, use @dataclass(frozen=True)
- For a non-default sorting style, use
from dataclasses import dataclass, field
,@dataclass(order=True)
, andsort_index: int = field(init=False, repr=False)
# Create object directly without a class (three items, two attributes each)
food = {
"muffin": 3.99,
"cupcake": 2.49,
"banana": 1.05,
}
for item in food:
print(f"The {item} costs £{food[item]}")
"""
The muffin costs £3.99
The cupcake costs £2.49
The banana costs £1.05
"""
# Class (two attributes, no methods)
class Food:
def __init__(self, name: str, price: float):
self.name = name
self.price = price
# Class (two attributes, no methods)
# exact same as above but with decorator (no need to manually add __init__ function, nor __repr__ or __eq__ )
from dataclasses import dataclass # Optional 'decorator' that saves writing __init__
@dataclass
class Food:
"""Information about the Food item (name and price)."""
name: str
price: float
food_items = [Food("pie", 15.00), Food("cake", 4.99), Food("soup", 7.50)]
for item in food_items:
print(f"The '{item.name}' costs £{item.price}")
"""
The pie costs £15.0
The cake costs £4.99
The soup costs £7.5
"""
# Import class (four attributes, two methods), create object from class
from car import Car
car_1 = Car(make="Chevy", model="Corvette", year=2021, colour="Green")
print(car_1.make) # Chevy
print(car_1.year) # 2021
car_1.drive() # The Corvette is now driving
car_1.stop() # The Corvette is now stopped