Python notes part5
Python notes part5
Recursion
1 What is Recursion?
Recursion is a programming technique where a function calls itself to solve a problem. Instead of using
loops, recursion breaks down a problem into smaller subproblems, solving each one step by step.
def recursive_function(parameters):
if base_condition: # Stopping condition (prevents infinite recursion)
return value
else:
return recursive_function(modified_parameters) # Function calls itself
Recursion follows the call stack mechanism, which stores function calls in memory until the base
condition is met.
Mathematical formula:
[ n! = n \times (n-1) \times (n-2) \times ... \times 1 ] or
[ n! = n \times (n-1)! ] with the base condition 1! = 1.
def factorial(n):
if n == 1: # Base condition
return 1
else:
Memory
High (stores function calls in stack) Low (uses a loop variable)
Usage
Fibonacci series:
[ F(n) = F(n-1) + F(n-2) ] with base conditions F(0) = 0, F(1) = 1.
def fibonacci(n):
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(6)) # Output: 8
Recursive calls:
fibonacci(6) → fibonacci(5) + fibonacci(4)
fibonacci(5) → fibonacci(4) + fibonacci(3)
...
fibonacci(2) → fibonacci(1) + fibonacci(0)
Pattern printing in Python refers to displaying characters, numbers, or symbols in a structured format
using loops. These patterns are often used for problem-solving, logic-building, and interview
preparation.
3 Basic Patterns
Pattern:
*
**
***
****
*****
n=5
for i in range(1, n+1):
for j in range(1, i+1):
print("*", end=" ")
print()
Pattern:
*****
****
***
**
*
n=5
for i in range(n, 0, -1):
for j in range(i):
print("*", end=" ")
print()
Pattern:
*
**
***
****
*****
n=5
for i in range(n):
print(" " * (n-i-1), end="")
print("* " * (i+1))
Spaces are printed first to shift stars towards the center.
Number of stars increases with each row.
4 Number-Based Patterns
Pattern:
1
12
123
1234
12345
n=5
for i in range(1, n+1):
for j in range(1, i+1):
print(j, end=" ")
print()
Pattern:
12345
1234
123
12
1
n=5
for i in range(n, 0, -1):
for j in range(1, i+1):
print(j, end=" ")
print()
6 Advanced Patterns
Pattern:
*
***
*****
*******
*********
*******
*****
***
*
n=5
for i in range(1, n+1, 2):
print(" " * ((n - i) // 2) + "*" * i)
for i in range(n-2, 0, -2):
print(" " * ((n - i) // 2) + "*" * i)
First loop prints the upper triangle.
Second loop prints the inverted lower triangle.
What is a Class?
A class is a blueprint for creating objects. It defines the structure and behavior (attributes and methods)
of objects.
What is an Object?
class Car:
def __init__(self, brand, model, year): # Constructor
self.brand = brand
self.model = model
self.year = year
def display_info(self):
print(f"Car: {self.brand} {self.model}, Year: {self.year}")
2 Encapsulation
Definition:
Syntax of Encapsulation:
class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private attribute
def get_balance(self):
return self.__balance
acc = BankAccount(1000)
acc.deposit(500) # Deposited: 500, New Balance: 1500
print(acc.get_balance()) # 1500
✔ Private attributes (__balance) cannot be accessed directly.
✔ Use getter methods (get_balance()) to access private data.
3 Abstraction
Definition:
Abstraction hides unnecessary details and exposes only the essential functionalities. It is implemented
using abstract classes.
Syntax of Abstraction:
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
circle = Circle(5)
print("Area:", circle.area()) # Output: Area: 78.5
✔ Abstract classes cannot be instantiated.
✔ Subclasses must implement all abstract methods.
4 Inheritance
Definition:
Inheritance allows one class (child class) to reuse the attributes and methods of another class (parent
class).
Types of Inheritance:
1) Single Inheritance
2) Multiple Inheritance
3) Multilevel Inheritance
4) Hierarchical Inheritance
5) Hybrid Inheritance
Single Inheritance
class Animal:
def sound(self):
print("Animals make sounds")
class Dog(Animal):
def bark(self):
print("Dog barks")
d = Dog()
Multiple Inheritance
class A:
def methodA(self):
print("Method from A")
class B:
def methodB(self):
print("Method from B")
obj = C()
obj.methodA() # Output: Method from A
obj.methodB() # Output: Method from B
Multilevel Inheritance
class Grandparent:
def grandparent_method(self):
print("Grandparent class")
class Parent(Grandparent):
def parent_method(self):
print("Parent class")
class Child(Parent):
def child_method(self):
print("Child class")
obj = Child()
obj.grandparent_method() # Output: Grandparent class
obj.parent_method() # Output: Parent class
Hierarchical Inheritance
class Parent:
def common_method(self):
print("This is a parent method")
class Child1(Parent):
pass
class Child2(Parent):
pass
obj1 = Child1()
obj2 = Child2()
5 Polymorphism
Definition:
Polymorphism allows different classes to have the same method name but different implementations.
Method Overriding
class Animal:
def make_sound(self):
print("Animal makes sound")
class Dog(Animal):
def make_sound(self): # Overriding
print("Dog barks")
d = Dog()
Python does not support true method overloading, but we can simulate it using default parameters.
class Math:
def add(self, a, b, c=0):
return a + b + c
m = Math()
print(m.add(2, 3)) # Output: 5
print(m.add(2, 3, 4)) # Output: 9