Module-5
• Classes and objects: Programmer-defined types, Attributes,
Rectangles, Instances as return values, Objects are mutable,
Copying,
• Classes and functions: Time, Pure functions, Modifiers,
Prototyping versus planning,
• Classes and methods: Object-oriented features, Printing objects,
Another example, A more complicated example,Theinit method,
Dept of MTE The __str__ method, Operator overloading, Type-based dispatch,
Polymorphism, Interface and implementation,
Introduction to Classes and Objects
• Definition: A class is a blueprint for creating objects (instances).
Objects have attributes and behaviors (methods).
• Why use them? Helps in structuring code and reusability
(Object-Oriented Programming )
Dept of MTE
• Explanation: In Python, classes provide a means of bundling
data and functionality together. Creating new classes allows you
to define custom data types.
• Notes: - Class is a blueprint; object is an instance. - Object-
Oriented Programming (OOP) supports modularity and code
reuse.
Programmer-defined Types
• You can define your own types using class.
• Example:
class Point:
pass
• Creates a new class Point. Objects can now be created from this
class.
Dept of MTE
• Explanation: You can define your own data types using the class
keyword.
• Notes: - Syntax: class ClassName: - Empty classes can use pass
initially.
Attributes
• Attributes are variables that belong to an object.
• Set them using dot notation:
class Point:
pass # Placeholder since the class has no content for now
# Creating an instance of the class
p = Point()
# Assigning attributes
p.x = 3
Dept of MTE
p.y = 4
# Printing the object (optional improvement below)
print(p.x, p.y)
Explanation: Attributes are variables attached to objects, holding
data.
• Notes: - Use dot notation to set/get attributes. - Example: p.x = 10
Rectangles Example
• Example class:
class Rectangle:
pass
#Create object and assign attributes:
box = Rectangle()
box.width = 100
box.height = 200
Dept of MTE
print("Width:", box.width)
print("Height:", box.height)
• Explanation: Illustrates object creation and attribute assignment using
Rectangle class.
• Notes: - Create Rectangle() object. - Set attributes like width, height.
Instances as Return Values
• Functions can return object instances.
• Example:
def grow(box, dwidth, dheight):
box.width += dwidth
box.height += dheight
return rect
Dept of MTE
• grow() that modifies the dimensions of a Rectangle object by
increasing its width and height
• Explanation: Functions can create and return new objects.
• Notes: - Helps modularize object creation and manipulation.
class Rectangle:
pass
# Create object and assign attributes:
box = Rectangle()
box.width = 100
box.height = 200
print("Width:", box.width)
print("Height:", box.height)
def grow(box , dwidth, dheight):
Dept of MTE box .width += dwidth
box .height += dheight
return box
# Grow it (use 'box', not 'rect')
grow(box, 50, 100)
print("After growing:")
print("Width:", box.width)
print("Height:", box.height)
Objects are Mutable
• Objects can be changed inside functions.
• Example:
def move(box, dx, dy):
box.x += dx
box.y += dy
Dept of MTE
• Explanation: Changes made to object attributes inside functions
persist outside.
• Notes: - Python objects are passed by reference. - Functions can
modify original objects
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
class Rectangle:
def __init__(self, width=0, height=0, corner=None):
self.width = width
self.height = height
self.corner = corner # Should be a Point object
Dept of MTE def move(box, dx, dy):
box.corner.x += dx
box.corner.y += dy
# Create a Point object
p = Point()
p.x = 3
p.y = 4
print(p.x, p.y) # Output: 3 4
# Create rectangle with width, height, and a corner at (10, 20)
corner_point = Point(10, 20)
box = Rectangle(100, 200, corner_point)
print("Width:", box.width)
print("Height:", box.height)
print("Before move:", box.corner.x, box.corner.y)
Dept of MTE
# Move the rectangle
move(box, 5, 10)
print("After move:", box.corner.x, box.corner.y)
Copying
• copy module helps in copying objects.
• Example:
import copy
box2 = copy.copy(box)
Dept of MTE • Explanation: Use copy module to create object copies.
• Notes: - copy.copy() for shallow copy.
copy.deepcopy() for deep copy.
import copy
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
class Rectangle:
def __init__(self, width=0, height=0, corner=None):
self.width = width
self.height = height
self.corner = corner
# Original object
Dept of MTE corner = Point(10, 20)
box = Rectangle(100, 200, corner)
# Shallow copy
box2 = copy.copy(box)
# Modify corner of copied box
#box2.corner.x = 999
# Outputs
print("Original box corner:", box.corner.x, box.corner.y)
print("Copied box corner:", box2.corner.x, box2.corner.y)
Time Class Example
• Define a Time class:
class Time:
pass
Assign attributes: hour, minute, second
Dept of MTE
• Explanation: Create a class to represent time data
(hours, minutes, seconds).
• Notes: - Class Time holds multiple related attributes.
class Time(object):
"""represents the time of day.
attributes: hour, minute, second"""
We can create a new Time object and assign
attributes for hours, minutes, and seconds:
time = Time()
time.hour = 11
time.minute = 59
time.second = 30
Dept of MTE
class Time:
pass
# Assign attributes: hour, minute, second
time = Time()
Dept of MTE time.hour = 11
time.minute = 59
time.second = 30
# Print using f-string
print(f"{time.hour:02d}:{time.minute:02d}:{time.second:02d}")
Pure Functions
• Don't modify the original object.
• Example:
def add_time(t1, t2):
result = Time()
result.hour = t1.hour + t2.hour
Dept of MTE return result
• Explanation: Functions that return new objects without altering
original ones.
• Notes: - Useful for non-destructive operations. - Enhances code
safety.
Modifiers
• Functions that modify object values directly.
• Opposite of pure functions.
def increment(time, seconds):
time.second += seconds
Dept of MTE
• Explanation: Functions that change the contents of an
object.
• Notes: - Opposite of pure functions. - Can lead to side-
effects.
class Time:
pass
def add_time(t1, t2):
result = Time()
# Add seconds
result.second = t1.second + t2.second
result.minute = t1.minute + t2.minute
result.hour = t1.hour + t2.hour
# Adjust for overflow
Dept of MTE
if result.second >= 60:
result.second -= 60
result.minute += 1
if result.minute >= 60:
result.minute -= 60
result.hour += 1
return result
# Create first Time object
time1 = Time()
time1.hour = 11
time1.minute = 59
time1.second = 30
# Create second Time object
time2 = Time()
time2.hour = 2
Dept of MTE time2.minute = 5
time2.second = 40
# Add the two times
sum_time = add_time(time1, time2)
# Print result
print(f"Sum of time: {sum_time.hour:02d}:{sum_time.minute:02d}:
Prototyping vs Planning
• Prototyping: Quick implementation to check logic.
• Planning: Carefully structuring classes and methods.
• Use both together for large projects.
• Explanation: Prototyping is quick implementation,
Dept of MTE
while planning is thoughtful design.
• Notes: - Start with a prototype, then refine. - Useful in
real-world development.
Object-Oriented Features
• Use of self in methods
• Example:
class Time:
def print_time(self):
print(f'{self.hour}:{self.minute}:{self.second}')
Dept of MTE
• Explanation: Introduction to methods inside classes using self.
• Notes: - Methods access object data via self.
class Time:
def print_time(self):
print(f'{self.hour:02d}:{self.minute:02d}:{self.second:02d}')
t = Time()
Dept of MTE t.hour = 9
t.minute = 5
t.second = 3
t.print_time()
Printing Objects
• Default: Shows memory address.
• Better: Use __str__ method to format output.
• Explanation: Customizing how objects appear when printed
using __str__.
• Notes: - Improves readability.
Dept of MTE
Another Example
• More usage of class with methods
def is_after(self, other):
return self.time_in_seconds() > other.time_in_seconds()
• Explanation: Using methods to compare object data.
Dept of MTE • Notes: - Reuse and encapsulate logic.
More Complicated Example
• Combine multiple methods:
def time_in_seconds(self):
return self.hour*3600 + self.minute*60 + self.second
• Explanation: Add method to compute time in seconds.
Dept of MTE • Notes: - Simplifies time comparisons.
The __init__ Method
• Constructor method.
class Time:
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
Dept of MTE self.second = second
• Explanation: Constructor to initialize object attributes at
creation.
• Notes: - Runs automatically when object is created.
The __str__ Method
• Controls how object is printed.
def __str__(self):
return f'{self.hour:02d}:{self.minute:02d}:{self.second:02d}'
• Explanation: Defines how object is represented as a string.
Dept of MTE • Notes: - Enables readable print output.
Operator Overloading
• Example: Overload + operator
def __add__(self, other):
return self.add_time(other)
• Explanation: Customize how operators behave for user-defined
classes.
Dept of MTE
• Notes: - Use methods like __add__, __sub__.
Type-based Dispatch
• Define behavior based on argument type.
def __add__(self, other):
if isinstance(other, Time):
return self.add_time(other)
else:
Dept of MTE return self.increment(other)
• Explanation: Change behavior of methods depending on
argument type.
• Notes: - Use isinstance() for checks.
Polymorphism
• Same function name can work on different types.
• Promotes flexibility and reuse.
• Explanation: Same method name can work with
different types.
Dept of MTE • Notes: - Increases flexibility. - Common in inheritance.
Interface and Implementation
• Interface: What the object can do (methods exposed)
• Implementation: How it does it (method body)
• Keep interface stable, implementation can change.
• Explanation: Interface defines method signatures;
implementation defines behavior.
Dept of MTE
• Notes: - Allows internal change without affecting user. - Key for
encapsulation.