4.6 Classes
Object-oriented programming (OOP) is a programming paradigm based on the concept of “objects”, which can contain data and code. The data is in the form of fields (often known as attributes or properties), and the code is in the form of procedures (often known as methods).
Generating an object from a class is called instantiation. You work with instances of a class, which are created by the process of instantiating an object from a class.
Using functions
class Student:
"""
A class is used to represent a student.
...
Attributes
----------
name: str
the name of the students
age: int
the age of the students
Methods
-------
learn()
Simulate a student's learning.
take_exam()
Simulate taking over good results.
"""
def __init__(self, name, age):
"""Initialize name and age attributes.
Attributes
----------
name: str
the name of the students
age: int
the age of the students
Returns:
None
"""
self.name = name
self.age = age
def learn(self):
"""Simulate a student's learning.
Prints status
Attributes
----------
name: str
the name of the students
age: int
the age of the students
Returns:
None
"""
print(f"{self.name} is now learning.")
def take_exam(self):
"""Simulate taking over good results.
Prints encouragement
Attributes
----------
name: str
the name of the students
age: int
the age of the students
Returns:
None
"""
print(f"{self.name} did great!")
print(f"Student1 is {student1.name} and is {student1.age}")
print(f"Student2 is {student2.name} and is {student2.age}")
student1 = Student("John Wick", 47)
student2 = Student("Macaulay Culkin", 12)
A method is a function that is a part of a class. Everything you learned about functions also applies to methods; the only difference in practice is that we’ll refer to methods as methods.
__init__
is a special method called a constructor that Python calls when you create a new instance of this class.
Other special methods include __str__
, __eq__
, and __len__
. You can override these methods to customize how they work with your objects.
Buzzwords of OOP
Class: A blueprint for how something should be defined. It doesn’t actually contain any data.
Object: An instance of a class. It contains the actual data.
Attribute: A bit of data inside a class or object.
Method: An action that a class or object can take.
Inheritance: The ability to extend a class to make a new class.
Composition: The ability to call functions from another class, or build a bigger class from smaller classes.
Encapsulation: A way to make sure that data can only be modified in certain ways.
Polymorphism: A way to make different classes interchangeable with each other.
Class variable: A variable that’s the same for every instance of a class.
Instance variable: A variable that’s unique to each instance of a class.
Constructor: The method that runs when an object is instantiated from a class.
What is Inheritance?
Inheritance is the process by which one class takes on the attributes and methods of another. Newly formed classes are called child classes, and the classes that child classes are derived from are called parent classes.
# Example on inheritance in Python
# Parent class
class Animal:
def __init__(self, name, weight):
self.name = name
self.weight = weight
def eat(self):
print(f"{self.name} is eating.")
def drink(self):
print(f"{self.name} is drinking.")
# Child class
class Frog(Animal):
def jump(self):
print(f"{self.name} is jumping.")
# Child class
class Dog(Animal):
def bark(self):
print(f"{self.name} is barking.")
frog = Frog("Kermit", 0.5)
dog = Dog("Scooby", 10)
frog.eat()
frog.drink()
frog.jump()
dog.eat()
dog.drink()
dog.bark()
What is Composition?
Composition is a way of building up larger classes from smaller ones. It refers to the way a class is made up of other classes as opposed to inheritance, which refers to the way a class is derived from another class.
# Example on composition in Python
class Book:
def __init__(self, title, price, author=None):
self.title = title
self.price = price
self.author = author
self.chapters = []
def add_chapter(self, chapter):
self.chapters.append(chapter)
def get_book_page_count(self):
result = 0
for ch in self.chapters:
result += ch.page_count
return result
class Author:
def __init__(self, fname, lname):
self.fname = fname
self.lname = lname
def __str__(self):
return f"{self.fname} {self.lname}"
class Chapter:
def __init__(self, name, page_count):
self.name = name
self.page_count = page_count
author = Author("Leo", "Tolstoy")
b1 = Book("War and Peace", 39.0, author)
What is Encapsulation?
Encapsulation is the process of restricting access to methods and variables in a class in order to prevent direct data modification so it prevents accidental modification of data.
# Example on encapsulation in Python
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
def get_name(self):
return self._name
def set_name(self, name):
self._name = name
def get_age(self):
return self._age
def set_age(self, age):
if age < 0:
raise ValueError("Age cannot be negative")
self._age = age
p = Person("John", 25)
print(p.get_name()) # Prints "John"
p.set_name("Jane")
print(p.get_name()) # Prints "Jane"
print(p.get_age()) # Prints 25
p.set_age(27)
print(p.get_age()) # Prints 27
p.set_age(-27) # Raises ValueError
What is Polymorphism?
Polymorphism in Python refers to the ability to use the same syntax for different types of objects. There are two main ways polymorphism is achieved in Python:
Inheritance and overriding - A parent class can be inherited by multiple child classes, each of which can override the parent class methods.
# Example on polymorphism in Python
class Shape:
def area(self):
pass
class Square(Shape):
def area(self):
# calculate area for square
pass
class Circle(Shape):
def area(self):
# calculate area for circle
pass
# Here Square and Circle inherit from Shape, but override the area method to provide their own implementation.
Duck typing - Different unrelated objects can have the same method names, allowing them to be used interchangeably.
class Car:
def drive(self):
print("Driving the car")
class Bike:
def drive(self):
print("Driving the bike")
# `vehicle` can refer to either a Car or Bike object
vehicle.drive()
# As long as objects have a drive method, they can be treated the same way despite having different underlying types.