Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mh0w/c3a8a3b8bb5ed2cac690f414b1c83d83 to your computer and use it in GitHub Desktop.
Save mh0w/c3a8a3b8bb5ed2cac690f414b1c83d83 to your computer and use it in GitHub Desktop.
Basic intro to Object Oriented Programming (OOP), classes, and objects in Python

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), and sort_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
class Car:
def __init__(self, make, model, year, colour):
self.make = make
self.model = model
self.year = year
self.colour = colour
def drive(self):
print(f"This {self.model} is now driving.")
def stop(self):
print(f"This {self.model} is now stopped.")
def set_model(self, model):
self.model = model
# Parent class
class Animal:
planet = "Earth"
quantity = 0
def __init__(self, name, age):
self.name = name
self.age = age
Animal.add_animal()
def describe(self):
print(f"I am {self.name} and I am {self.age} years old")
def speak(self):
print("Unknown")
@classmethod
def add_animal(cls):
cls.quantity += 1
# Child class
class Cat(Animal):
# Add one additional attribute (colour)
def __init__(self, name, age, colour):
super().__init__(name, age)
self.colour = colour
def speak(self):
print("Meow)
def describe(self):
print(f"I am {self.name} and I am {self.age} years old and I am {self.colour}")
# Child class
class Dog(Animal):
def speak(self):
print("Bark")
a1 = Animal("Tilly", 5)
a2 = Cat("Sully", 6, "Beige")
a3 = Dog("Fully", 4)
a1.speak() # Unknown
a2.speak() # Meow
a3.speak() # Bark
print(Animal.planet) # Earth
print(a3.planet() # Earth
class CommonFunctions:
@staticmethod
def add5(x):
return x + 5
@staticmethod
def add10(x)
return x + 10
print(CommonFunctions.add5(3))
print(CommonFunctions.add10(4))
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade # 0 - 100
def get_grade(self):
return self.grade
class Course:
def __init__(self, name, max_students):
self.name = name
self.max_students = max_students
self.students = []
def add_students(self, student):
if len(self.students) < self.students:
self.students.append(student)
return True
return False
def get_average_grade(self):
value = 0
for student in self.students:
value += student.get(grade)
return value / len(self.students)
s1 = Student("Tim", 19, 95)
s2 = Student("Bill", 19, 75)
s3 = Student("Jill", 19, 65)
course1 = Course("Art", 2)
course1.add_students(s1)
course1.add_students(s2)
course1.add_students(s3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment