Unit 5 Pythn
Unit 5 Pythn
• For example, the + operator will perform arithmetic addition on two numbers, merge two
lists, or concatenate two strings
• This feature in Python that allows the same operator to have different meanings
according to the context is called operator overloading
• Python uses special methods (magic methods or dunder methods) to implement operator
overloading. These methods are surrounded by double underscores (e.g., __add__,
__sub__).
✓ Where to Use It
• Mathematical Classes: For complex numbers, vectors, matrices, etc.
• Custom Data Structures: Such as linked lists, trees, etc.
• String and File Handling: Overloading operators like + for concatenation.
+ __add__(self, other)
- __sub__(self, other)
* __mul__(self, other)
/ __truediv__(self, other)
// __floordiv__(self, other)
% __mod__(self, other)
** __pow__(self, other)
| __or__(self, other)
^ __xor__(self, other)
• Comparison Operators:
== __EQ__(SELF, OTHER)
!= __NE__(SELF, OTHER)
• Assignment Operators:
-= __ISUB__(SELF, OTHER)
+= __IADD__(SELF, OTHER)
*= __IMUL__(SELF, OTHER)
/= __IDIV__(SELF, OTHER)
%= __IMOD__(SELF, OTHER)
|= __IOR__(SELF, OTHER)
^= __IXOR__(SELF, OTHER)
• Unary Operator:
Operator Magic Function
- __NEG__(SELF, OTHER)
+ __POS__(SELF, OTHER)
~ __INVERT__(SELF, OTHER)
➢ Reverse adding
Reverse adding in Python typically refers to appending elements to the beginning of a list rather
than the end.
You can prepend an element by creating a new list with the element followed by the original
list.
original_list = [2, 3, 4]
element_to_prepend = 1
The insert method can add an element at a specified position. To add to the beginning, specify
the position as 0.
original_list = [2, 3, 4]
element_to_prepend = 1
original_list.insert(0, element_to_prepend)
• Using Deque:
The collections.deque class provides an efficient way to add elements to both ends of a list.
element_to_prepend = 1
original_list.appendleft(element_to_prepend)
Another method is to reverse the list, append the element, and then reverse it back.
original_list = [2, 3, 4]
element_to_prepend = 1
original_list.reverse()
original_list.append(element_to_prepend)
original_list.reverse()
When considering reverse adding in Python within the context of object-oriented programming
(OOP), it might refer to a more abstract concept. This could involve defining a custom behavior
for a class to handle addition operations in a specific manner. Here, "reverse adding" could be
implemented by overloading the __radd__ method, which stands for "reverse addition."
In Python, the __add__ method is used to define the behavior of the + operator. The __radd__
method is called when the left operand does not support the addition operation with the right
operand, and the right operand implements the __radd__ method.
Example: -
class MyNumber:
self.value = value
def __repr__(self):
return f"MyNumber({self.value})"
# Example usage
a = MyNumber(10)
Note: -
1. __add__ Method: This method is called when your custom class instance is on the left
side of the + operator.
2. __radd__ Method: This method is called when your custom class instance is on the
right side of the + operator, and the left operand does not support the operation with the
right operand.
➢ Overriding
• Multiple function with same name and same number of parameters
• If we write method in the both classes, parent class and child class then the parent
class’s method is not available to the child class.
• In this case only child class’s method is accessible which means child class’s method is
replacing parent class’s method.
• Method overriding is used when programmer want to modify the existing behavior of a
method.
➢ __getitem__() and __setitem__()
Here's a comparison table for __getitem__() and __setitem__() in Python:
# Usage
my_collection = MyCollection([1, 2, 3, 4, 5])
print(3 in my_collection) # Output: True
print(6 in my_collection) # Output: False
# Usage
callable_instance = CallableExample("Hello, World!")
callable_instance(3) # Output: Hello, World!
# Hello, World!
# Hello, World!
Here's an example to demonstrate how you can use multiple except blocks:
try:
result = a / b
except ZeroDivisionError:
except TypeError:
except Exception as e:
else:
finally:
print("Execution completed.")
# Test cases
try:
except ZeroDivisionError:
except ValueError:
except Exception as e:
print(f"Error: {e}")
else:
print(f"Result: {result}")
finally:
print("Execution complete.")
➢ Raising exceptions
Raising exceptions in Python allows you to signal that an error or exceptional
condition has occurred during the execution of your code. This is particularly
useful when you encounter situations where normal program flow cannot proceed
due to unexpected conditions.
Example 1
class CustomError(Exception):
self.message = message
super().__init__(self.message)
def validate_age(age):
if age < 0:
else:
print("Age is valid")
try:
except CustomError as e:
except ValueError as e:
try:
if num <= 0:
except ValueError as e:
print(f"Error: {e}") 0
Syntax: -
try:
except ZeroDivisionError:
finally:
# Code that will always execute, regardless of whether an exception was raised or not
print("Finally block: Cleaning up resources or finalizing operations")
Note: - The ‘finally’ block is optional but if present, must follow all except blocks.
Assignment questions
1. class Person:
self.name = name
self.age = age
p1 = Person("Alice", 20)
p2 = Person("Bob", 30)
2. class Fruit:
self.num = num
obj1 = Fruit(10)
obj2 = Fruit(25)
print(sum)
3. What happens if you raise an exception with arguments but do not handle it?
4. How can you catch multiple exceptions at once in Python?
5. What are logic errors?Give Examples.
6. What is the difference between the Exception class and the Base Exception class in
Python?
7. Differentiate error and exception
8. How can you ensure that a certain code block runs no matter whether there’s an
exception or not.
9. What is the output of the following snippet
a = 'welcome to Python'
b = ['welcome', 'Python']
print(a.__len__())
print(len(a))
print( b[0])
print(b.__getitem__(0))