Module5 Notes-1
Module5 Notes-1
What is a Class?
• To define a class, use the “class” keyword followed by the name of the
class (typically written in PascalCase).
syntax:
class ClassName:
self.attribute1 = attribute1
self.attribute2 = attribute2
def method_name(self):
pass
• It is used to access attributes that belong to the class and methods within
the class.
Example:
class Car:
self.brand = brand
self.model = model
self.year = year
def display_info(self):
In this example:
• The __init__ method initializes the class with three attributes: brand,
model, and year.
Once you have defined a class, you can create instances (objects) of that class
by calling the class as if it were a function, passing the required arguments to
the __init__ method.
In this example, my_car is an instance of the Car class, with the brand
"Toyota", model "Corolla", and year 2020.
Accessing Class Members
1. Attributes: These are the data values associated with an instance of the
class.
Accessing Attributes
You can access the attributes of an instance using the dot (.) notation:
Accessing Methods
class Rectangle:
self.width = width
self.height = height
This creates a class with two attributes:
• width
• height
Each Rectangle object will have its own width and height.
r1 = Rectangle(10, 5)
r2 = Rectangle(4, 7)
Here,
class Rectangle:
self.width = width
self.height = height
def area(self):
def perimeter(self):
Usage of Methods:
r1 = Rectangle(10, 5)
Summary Table:
Component Meaning
Example:
class Rectangle:
self.width = width
self.height = height
def area(self):
def create_square(side_length):
sq = create_square(6)
Here:
Benefit Explanation
Can reuse the same function to create many
Code reuse
instances
class Student:
self.name = name
self.roll_no = roll_no
def create_student():
s1 = create_student()
Key Takeaways:
Concept Description
Access like any object After return, use dot notation normally
In Python, most built-in types like list, dict, and custom class instances (like
Student, Rectangle) are mutable.
Example:
class Rectangle:
self.width = width
self.height = height
def area(self):
r1 = Rectangle(10, 5)
# Change attributes
r1.width = 20
Summary Table:
Term Meaning
Copying an object means creating a new object with the same attributes or
data as an existing one.
r1 = Rectangle(10, 5)
r2.width = 20
import copy
class Rectangle:
self.width = width
self.height = height
r1 = Rectangle(10, 5)
r2.width = 20
• r2 is a new object.
• Changes to r2 do not affect r1.
Deep copy is used when your object contains other mutable objects inside it
(like lists).
class Box:
self.items = items
b1 = Box(["apple", "banana"])
b2 = copy.deepcopy(b1)
b2.items.append("cherry")
Key Differences:
Summary:
_ _init_ _ method
class MyClass:
self.x = x
self.y = y
print(obj.x)
print(obj.y)
Output: 10
Output: 20
In this example, the `__init__` method takes three parameters: `self`, `x`, and
`y`.
`self` refers to the instance/object itself and is automatically passed when the
method is called.
The `x` and `y` parameters are used to initialize the instance variables `x` and
`y` respectively.
In Python, the `__str__` method is a special method used to define the string
representation of an object.
When you use built-in functions like `str()` or `print()` on an object, Python
calls the object's `__str__` method to get its string representation.
class MyClass:
self.x = x
self.y = y
print(obj)
Output:
When `print(obj)` is called, Python internally calls `obj._ _str_ _()` to get the
string representation of the object, which is then printed.
Operator overloading
This means that you can redefine the meaning of operators such as `+`, `-`, `*`,
`/`, `==`, `!=`, `<`, `>`, and many others for your own classes.
For example, you can define what it means to add two instances of a custom
class together, or how to compare them for equality.
class Point:
self.x = x
self.y = y
point1 = Point(1, 2)
point2 = Point(3, 4)
# Output: (4, 6)
In this example:
- The `_ _add_ _` method is defined to override the behavior of the `+` operator
for `Point` objects.
When two `Point` objects are added together using the `+` operator (`point1 +
point2`), the `_ _add_ _` method is called, and the result is a new `Point` object
with coordinates that are the sum of the corresponding coordinates of the
operands.
By implementing these special methods, you can define custom behavior for
operators in your classes, allowing them to behave naturally in Python
expressions and operations.
Inheritance
class Animal:
self.name = name
def speak(self):
class Dog(Animal):
def speak(self):
print("{} barks".format(self.name))
dog1 = Dog("Tommy")
dog1.speak()
Output:
Tommy barks
Explanation:
1. Class Animal:
o It has:
▪ An __init__() method (constructor) that accepts name and
assigns it to self.name.
2. Class Dog:
3. Object Creation:
4. Method Call:
o dog1.speak() calls the speak() method from the Dog class (not the
one in Animal).
Inheritance promotes code reuse and simplifies the design of your program by
allowing you to create specialized classes that inherit common attributes and
behaviors from a base class. This makes your code more maintainable and
reduces redundancy.
Polymorphism
1. Method Overriding:
def speak(self):
print("Animal speaks")
def speak(self):
print("Dog barks")
# Creating instances
animal = Animal()
dog = Dog()
# Polymorphism
animal.speak()
dog.speak()
Default arguments:
class Calculator:
return a + b
calc = Calculator()
print(calc.add(5))
Output: 5
print(calc.add(2, 3))
Output: 5
Example using variable-length arguments:
class Calculator:
return sum(args)
calc = Calculator()
print(calc.add(5))
Output: 5
print(calc.add(2, 3))
Output: 5
print(calc.add(1, 2, 3, 4))
Output: 10
In both examples, the `add` method behaves differently based on the number
of arguments passed to it, demonstrating polymorphic behaviour.
d = dict()
for c in s:
if c not in d:
d[c] = 1
else:
d[c] = d[c]+1
return d
histogram(t)
Type-Based Dispatch
It's useful in data science, where different input types might need to be
processed by the same function.
Working.
• You can also use the @overload annotation to support multiple dispatch.
• It can create a common API for functions that perform similar tasks.
Example:
def process(value):
if isinstance(value, int):
else:
# Test cases
A design principle that helps achieve that goal is to keep interfaces separate
from implementations.
For objects, that means that the methods a class provides should not depend
on how the attributes are represented.
What Is an Interface?
What Is Implementation?
Implementation is the actual code or logic written inside the class methods to
fulfill the interface.
Concept Real-world Analogy
The user presses a button (interface), not knowing how signals are sent
(implementation).
Python Example:
Let’s create a class that behaves like a shape (e.g., rectangle or circle):
class Shape:
def area(self):
def perimeter(self):
This class defines the interface (a set of method names that other classes must
follow).
class Rectangle(Shape):
self.width = width
self.height = height
def area(self):
def perimeter(self):
def print_shape_info(shape):
print("Area:", shape.area())
print("Perimeter:", shape.perimeter())
rect = Rectangle(5, 4)
print_shape_info(rect)
Keeping the interface separate from the implementation means that you have to
hide the attributes.
Code in other parts of the program (outside the class definition) should use
methods to read and modify the state of the object.
They should not access the attributes directly. This principle is called
information hiding;
Pure functions
• The function always produces the same output for the same input.
• The function does not modify any external state or variable outside its
scope.
In simple terms, a pure function always returns the same result when called with
the same arguments and does not alter any external variables or state (such as
global variables, attributes).
class Time:
self.hours = hours
self.minutes = minutes
def total_minutes(self):
These are methods that change the value of an object's attributes or perform
operations that alter the state.
Example
class Time:
self.hours = hours
self.minutes = minutes
self.minutes += mins
self.hours += 1
self.minutes -= 60
add_minutes() is a modifier
Definition
• Prototyping:
• Planning:
Emphasis on organization,
Emphasis on experimentation
Focus resource allocation, and
and iterative improvement.
setting clear goals.