Object Composition
Understanding Composition
Composition occurs when an object contains another object as one of its attributes, allowing complex structures to be built from simpler components.
Benefits of Composition
Composition reduces code duplication and enhances program extensibility by promoting code reuse and modular design.
Implementing Composition
Create instances of one class and assign them as attributes to another class instance:
class Person:
def __init__(self, name):
self.name = name
class BirthDate:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def display_birth_info(self, person):
print(f"""
==={person.name}'s Birth Details===
Year: {self.year}
Month: {self.month}
Day: {self.day}
""")
class Instructor(Person):
pass
class Learner(Person):
pass
prof = Instructor('John Doe')
b_date = BirthDate(1985, 7, 15)
prof.birth_info = b_date
prof.birth_info.display_birth_info(prof)
Course Enrollment System Example
class Person:
def __init__(self, name):
self.name = name
self.courses = []
def enroll_course(self, course_obj):
self.courses.append(course_obj)
print(f'{self.name} enrolled in {course_obj.name}')
def show_courses(self):
print(f'{self.name}\'s enrolled courses:')
for course in self.courses:
print(f"""
Course: {course.name}
Duration: {course.duration}
Price: {course.price}
""")
class Course:
def __init__(self, name, duration, price):
self.name = name
self.duration = duration
self.price = price
class Student(Person):
def __init__(self, name, grade):
super().__init__(name)
class Teacher(Person):
def __init__(self, name, rank):
super().__init__(name)
teacher = Teacher('Dr. Smith', 'Senior')
student = Student('Alice', 'A')
python_course = Course('Python', 6, 20000)
linux_course = Course('Linux', 4, 1000)
teacher.enroll_course(python_course)
teacher.enroll_course(linux_course)
teacher.show_courses()
Encapsulation
Concept of Encapsulation
Encapsulation bundles related attributes and methods into objects, controlling access through well-defined interfaces.
Purpose of Encapsulation
Encapsulation organizes code into logical units and protects internal state from unintended modifications.
Implementation Methods
Define attributes and methods within classes, and control access using Python's naming convensions and property decorators.
Access Control Mechanisms
Private Attributes
Prefix attributes with double underscores to indicate they shouldn't be accessed directly from outside the class.
Controlled Access
Provide methods to get and set private attributes with validation logic:
class SecureData:
__secret_value = 'confidential'
def get_value(self):
return self.__secret_value
def set_value(self, new_val):
self.__secret_value = new_val
data = SecureData()
print(data.get_value())
data.set_value('updated_secret')
print(data.get_value())
Teacher Information Management Example
class Educator:
def __init__(self, name, age, gender):
self.__name = name
self.__age = age
self.__gender = gender
def show_info(self):
username = input('Username: ')
password = input('Password: ')
if username == 'admin' and password == 'secure123':
print(f"""
Educator Details:
Name: {self.__name}
Age: {self.__age}
Gender: {self.__gender}
""")
def update_info(self, name, age, gender):
if not all([isinstance(name, str), isinstance(age, int), isinstance(gender, str)]):
raise ValueError('Invalid input types')
self.__name = name
self.__age = age
self.__gender = gender
educator = Educator('Dr. Brown', 42, 'male')
educator.update_info('Prof. Green', 45, 'female')
educator.show_info()
Property Decorator
Using @property
The @property decorator allows methods to be accessed like attributes while maintaining computation logic:
class HealthMetrics:
def __init__(self, weight_kg, height_m):
self.weight = weight_kg
self.height = height_m
@property
def bmi(self):
return self.weight / (self.height ** 2)
person = HealthMetrics(70, 1.8)
print(person.bmi)
Polymorphism
Polymorphic Behavior
Different classes can implement the same method name with different behaviors:
class Animal:
def vocalize(self):
print('Animal sound')
class Canine(Animal):
def vocalize(self):
print('Bark')
class Feline(Animal):
def vocalize(self):
print('Meow')
dog = Canine()
cat = Feline()
dog.vocalize()
cat.vocalize()
Duck Typing
Python uses duck typing where objects are judged by their methods rather than their types:
class Bird:
def sound(self):
print('Chirp')
class Instrument:
def sound(self):
print('Play music')
def make_sound(entity):
entity.sound()
sparrow = Bird()
piano = Instrument()
make_sound(sparrow)
make_sound(piano)
Standardized Interfaces
Create functions that work with any object implementing required methods:
def calculate_length(item):
return item.__len__()
text = "hello"
numbers = [1, 2, 3, 4]
print(calculate_length(text))
print(calculate_length(numbers))