0% found this document useful (0 votes)
4 views26 pages

Lecture9 Object Oriented Programming Python

The document provides an overview of Object Oriented Programming in Python, focusing on special (magic) methods that enable custom object behavior for built-in operations. It covers various categories of magic methods including construction, representation, comparison, arithmetic, and container methods, along with examples for each. Additionally, it discusses the implementation of callable objects, context managers, attribute access, and hashing and copying functionalities.

Uploaded by

jejelicious2008
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views26 pages

Lecture9 Object Oriented Programming Python

The document provides an overview of Object Oriented Programming in Python, focusing on special (magic) methods that enable custom object behavior for built-in operations. It covers various categories of magic methods including construction, representation, comparison, arithmetic, and container methods, along with examples for each. Additionally, it discusses the implementation of callable objects, context managers, attribute access, and hashing and copying functionalities.

Uploaded by

jejelicious2008
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Object Oriented Programming(Python)

Emmanuel Ali(PhD)

May 21, 2026

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 1 / 26


Outline

1 Magic Methods

2 Construction and Initialization

3 Representation Magic Methods

4 Comparison Magic Methods

5 Numeric Magic Methods

6 Container Magic Methods

7 Callable and Context Manager Magic Methods

8 Other Useful Magic Methods

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 2 / 26


What Are Special (Magic) Methods?
Special methods (also called dunder methods because they have double
underscores before and after their names) allow developers to define how
objects behave with built-in operations such as printing, arithmetic,
comparison, indexing, iteration, and more.
Dunder methods are predefined method names in Python that begin and end
with double underscores:
__methodname__

Predefined method names surrounded by double underscores.


Automatically invoked by Python.
Allow objects to behave like built-in types.
Examples:
__init__
__str__
__add__
__len__
Important: We do NOT call them
Emmanuel Ali(PhD) 2nddirectly
Semester — Python calls them.
May 21, 2026 3 / 26
Why Use Magic Methods?

Make custom objects behave like built-in types


Enable operator overloading (like +, -, *, /)
Create more intuitive interfaces for your classes
Control object creation, representation, and destruction
Implement protocols (e.g., context managers, descriptors)
Enhance readability and expressiveness of code

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 4 / 26


Object Construction Magic Methods

__new__(cls, ...): Static method called before __init__


Creates and returns a new instance
Rarely overridden except for singletons, immutables, or metaclasses
__init__(self, ...): Initialize a newly created instance
Most common constructor method
Sets up instance attributes
__del__(self): Called when object is garbage collected
Used for cleanup operations
Should not be relied upon for critical cleanup

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 5 / 26


Construction Example
class Person :
def __new__ ( cls , name , age ) :
print ( f " Creating a new Person object " )
# Call the parent class 's __new__ method
instance = super () . __new__ ( cls )
return instance

def __init__ ( self , name , age ) :


print ( f " Initializing Person object " )
self . name = name
self . age = age

def __del__ ( self ) :


print ( f " { self . name } is being destroyed " )

# Creating an instance
p = Person ( " Alice " , 30)
# Output :
# Creating a new Person object
# Initializing Person object
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 6 / 26
String Representation Methods

__str__(self): Human-readable string representation


Called by the str() function and print()
Should return a friendly, readable description
__repr__(self): Developer-readable string representation
Called by the repr() function
Should ideally be valid Python code to recreate the object
Used as fallback if __str__ is not defined
__format__(self, format_spec): Custom string formatting
Called by the format() function and f-strings
Allows for custom format specifications

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 7 / 26


class Point :
def __init__ ( self , x , y ) :
self . x = x
self . y = y

def __str__ ( self ) :


return f " Point at ({ self . x } , { self . y }) "

def __repr__ ( self ) :


return f " Point ({ self . x } , { self . y }) "

def __format__ ( self , format_spec ) :


if format_spec == " polar " :
r = ( self . x **2 + self . y **2) **0.5
theta = math . atan2 ( self .y , self . x )
return f " r ={ r :.2 f } , ={ theta :.2 f } "
return str ( self )

p = Point (3 , 4)
p
print ( str ( p ) )
print ( repr ( p ) )
print ( f " { p : polar } " )
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 8 / 26
Comparison Magic Methods

__eq__(self, other): Equality (==)


__ne__(self, other): Inequality (!=)
__lt__(self, other): Less than (<)
__le__(self, other): Less than or equal to (<=)
__gt__(self, other): Greater than (>)
__ge__(self, other): Greater than or equal to (>=)
__bool__(self): Truth value testing (if obj:)
If __bool__ is not implemented, Python falls back to __len__

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 9 / 26


class Temperature :
def __init__ ( self , celsius ) :
self . celsius = celsius

def __eq__ ( self , other ) :


if isinstance ( other , Temperature ) :
return self . celsius == other . celsius
return False

def __lt__ ( self , other ) :


if isinstance ( other , Temperature ) :
return self . celsius < other . celsius
return NotImplemented

def __bool__ ( self ) :


return self . celsius > 0 # True if above freezing

t1 = Temperature (20)
t2 = Temperature (30)
t3 = Temperature (20)
print ( t1 == t3 )
print ( t1 < t2 )
print ( bool ( t1 ) )
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 10 / 26
Arithmetic Operator Methods

__add__(self, other): Addition (+)


__sub__(self, other): Subtraction (-)
__mul__(self, other): Multiplication (*)
__truediv__(self, other): Division (/)
__floordiv__(self, other): Floor division (//)
__mod__(self, other): Modulo (
__pow__(self, other): Power (**)
There are also right-side versions (__radd__, __rsub__, etc.)
And in-place versions (__iadd__, __isub__, etc.)

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 11 / 26


Arithmetic Operator Example

class Vector :
def __init__ ( self , x , y ) :
self . x = x
self . y = y

def __add__ ( self , other ) :


if isinstance ( other , Vector ) :
return Vector ( self . x + other .x , self . y + other . y
)
return NotImplemented

def __mul__ ( self , scalar ) :


if isinstance ( scalar , ( int , float ) ) :
return Vector ( self . x * scalar , self . y * scalar )
return NotImplemented

def __rmul__ ( self , scalar ) :


# Called when scalar * vector
return self . __mul__ ( scalar )

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 12 / 26


def __str__ ( self ) :
return f " Vector ({ self . x } , { self . y }) "

v1 = Vector (1 , 2)
v2 = Vector (3 , 4)
print ( v1 + v2 )
print ( v1 * 3)
print (2 * v2 )

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 13 / 26


Unary Operators and Functions

__neg__(self): Negation (-obj)


__pos__(self): Positive (+obj)
__abs__(self): Absolute value (abs(obj))
__round__(self, n): Rounding (round(obj, n))
__floor__(self): Floor ([Link](obj))
__ceil__(self): Ceiling ([Link](obj))
__trunc__(self): Truncation ([Link](obj))

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 14 / 26


Unary Example
class Angle :
def __init__ ( self , degrees ) :
self . degrees = degrees % 360

def __neg__ ( self ) :


return Angle ( - self . degrees )

def __abs__ ( self ) :


return Angle ( abs ( self . degrees ) )

def __round__ ( self , n =0) :


return Angle ( round ( self . degrees , n ) )

def __str__ ( self ) :


return f " { self . degrees } "

angle = Angle (45)


print ( - angle ) # 315
print ( abs ( Angle ( -30) ) ) # 30
print ( round ( Angle (47.8) ) ) # 48
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 15 / 26
Container Magic Methods

__len__(self): Length (len(obj))


__getitem__(self, key): Item access (obj[key])
__setitem__(self, key, value): Item assignment (obj[key] =
value)
__delitem__(self, key): Item deletion (del obj[key])
__contains__(self, item): Membership test (item in obj)
__iter__(self): Iteration (for x in obj)
__reversed__(self): Reversed iteration (reversed(obj))

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 16 / 26


class ShoppingCart :
def __init__ ( self ) :
self . items = {} # item -> quantity

def add ( self , item , quantity =1) :


self . items [ item ] = self . items . get ( item , 0) +
quantity

def __getitem__ ( self , item ) :


return self . items . get ( item , 0)

def __setitem__ ( self , item , quantity ) :


if quantity <= 0:
if item in self . items :
del self . items [ item ]
else :
self . items [ item ] = quantity

def __len__ ( self ) :


return sum ( self . items . values () )

def __contains__ ( self , item ) :


return item in self . items
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 17 / 26
def __iter__ ( self ) :
for item , quantity in self . items . items () :
for _ in range ( quantity ) :
yield item

def __str__ ( self ) :


if not self . items :
return " Empty Cart "
return " \ n " . join ( f " { q } x { i } " for i , q in self . items .
items () )

cart = ShoppingCart ()
cart . add ( " apple " , 3)
cart . add ( " banana " , 2)

print ( len ( cart ) )


print ( " apple " in cart )
print ( cart [ " apple " ])

cart [ " orange " ] = 4


del cart [ " banana " ]
for item in cart :
print ( f " Item : { item } " )
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 18 / 26
Callable Objects
__call__(self, ...): Makes object callable like a function
Allows an instance to be called as a function: instance()
Useful for:
Function-like objects (functors)
Objects that maintain state between calls
Callback objects
Implementing decorators
class Counter :
def __init__ ( self ) :
self . count = 0

def __call__ ( self ) :


self . count += 1
return self . count

c = Counter ()
print ( c () ) # 1
print ( c () ) # 2
print ( c () ) # 3
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 19 / 26
Context Managers

__enter__(self): Enter the context (with obj as x:)


__exit__(self, exc_type, exc_val, exc_tb): Exit the
context
Used to manage resources (files, locks, connections)
Ensures proper cleanup even if exceptions occur

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 20 / 26


Context Managers
class Data base Conn ec tion :
def __init__ ( self , db_name ) :
self . db_name = db_name
self . connected = False

def __enter__ ( self ) :


print ( f " Connecting to { self . db_name } " )
self . connected = True
return self # The object assigned to the ' as '
variable

def __exit__ ( self , exc_type , exc_val , exc_tb ) :


print ( f " Disconnecting from { self . db_name } " )
self . connected = False
# Return True to suppress exceptions , False to
propagate

with Datab aseConne ct ion ( " users . db " ) as db :


print ( f " Connected : { db . connected } " )
# Do database operations
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 21 / 26
Attribute Access Magic Methods
__getattr__(self, name): Called when attribute lookup fails
__getattribute__(self, name): Called for all attribute access
__setattr__(self, name, value): Called when setting
attributes
__delattr__(self, name): Called when deleting attributes
__dir__(self): Called by dir() function
class Dyna micAttributes :
def __getattr__ ( self , name ) :
return f " Attribute { name } not found "

def __setattr__ ( self , name , value ) :


print ( f " Setting { name } to { value } " )
super () . __setattr__ ( name , value )

obj = DynamicAttributes ()
obj . x = 10 # Setting x to 10
print ( obj . y ) # Attribute y not found

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 22 / 26


Hashing and Copying

__hash__(self): Hash function for dictionaries and sets


__copy__(self): Create a shallow copy ([Link]())
__deepcopy__(self, memo): Create a deep copy
([Link]())

Emmanuel Ali(PhD) 2nd Semester May 21, 2026 23 / 26


Hashing and Copying
import copy

class Point :
def __init__ ( self , x , y ) :
self . x = x
self . y = y

def __eq__ ( self , other ) :


if not isinstance ( other , Point ) :
return NotImplemented
return self . x == other . x and self . y == other . y

def __hash__ ( self ) :


return hash (( self .x , self . y ) )

def __copy__ ( self ) :


return Point ( self .x , self . y )

p1 = Point (1 , 2)
p2 = copy . copy ( p1 ) # Uses __copy__
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 24 / 26
Exercise:
Create a class named BankAccount. When initializing an instance, it
must accept and store:
owner (string): The name of the account holder.
balance (float): The starting financial balance.
Implement the following behaviors inside your BankAccount class:
1. Text Representation (__str__): Should return a clean,
reader-friendly string format.
Example Output: "Account Holder: Ayo | Balance: $1500.00"
2. Combining Accounts (__add__): Allows two accounts to be
combined using the + operator. It should return a new BankAccount
instance where:
The new owner name combines both (e.g., "Ayo & Chidi").
The new balance is the sum of both accounts’ balances.
3. Comparing Balances (__lt__): Allows accounts to be evaluated
using the less-than (<) operator based purely on their numeric balance.
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 25 / 26
Exercise: Test Your Implementation
Add the following test execution block at the bottom of your script to
verify your logic:
acc1 = BankAccount ( " Ayo " , 1500.00)
acc2 = BankAccount ( " Chidi " , 2500.50)

print ( acc1 ) # Expected : Account Holder : Alice | Balance :


$1500 .00

if acc1 < acc2 :


print ( f " { acc1 . owner } has less money than { acc2 . owner }. " )

joint = acc1 + acc2


print ( joint ) # Expected : Account Holder : Alice & Bob |
Balance : $4000 .50

Addition
Implement __eq__ to compare equality (==) of balances.
Add Type Checking to __add__ so adding an integer/float directly
Emmanuel Ali(PhD) 2nd Semester May 21, 2026 26 / 26

You might also like