0% found this document useful (0 votes)
5 views87 pages

Python Programming Basics Guide

The document provides a comprehensive introduction to Python, covering its definition, features, data types, operators, conditional statements, loops, functions, and object-oriented programming concepts. It details both single-valued and multi-valued data types, as well as essential operations and methods for strings and lists. Additionally, it touches on advanced Python topics such as lambda functions, file handling, and exception handling.

Uploaded by

fun98324
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)
5 views87 pages

Python Programming Basics Guide

The document provides a comprehensive introduction to Python, covering its definition, features, data types, operators, conditional statements, loops, functions, and object-oriented programming concepts. It details both single-valued and multi-valued data types, as well as essential operations and methods for strings and lists. Additionally, it touches on advanced Python topics such as lambda functions, file handling, and exception handling.

Uploaded by

fun98324
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

● Main Topic: Introdunction to Python

○ Sub Topic: Definition Page No: 2


○ Sub Topic: Features of Python Page No: 2
○ Sub Topic: keywords Page No: 3
○ Sub Topic: Variable Page No: 4

● Main Topic: Data Types in Python


○ Sub Topic: Single-Valued Data Types Page No: 5
▪ Int Page No: 5
▪ Float Page No:5
▪ Complex Page No: 6
▪ Bool Page No: 6

○ Sub Topic: Multi-Valued Data Types Page No: 6


▪ String Page No: 7-10
▪ List Page No: 10-13
▪ Tuple Page No: 13-14
▪ Set Page No: 15-18
▪ Dictionary Page No: 18-22

○ Sub Topic: Copy Operation Page No: 22-25

● Main Topic: Operators in Python Page No: 25


○ Sub Topic: Arithmetic Operators Page No: 26
○ Sub Topic: Assignment Operators Page No: 27
○ Sub Topic: Comparison Operators Page No: 27
○ Sub Topic: Logical Operators Page No: 28
○ Sub Topic: Bitwise Operators Page No: 28
○ Sub Topic: Identity Operators Page No: 29
○ Sub Topic: Membership Operators Page No: 29

● Main Topic: Conditional Statement In Python 29


Page No:
○ Sub Topic: if Page No: 31
○ Sub Topic: if-else Page No: 31
○ Sub Topic: if-elif-else Page No: 32
○ Sub Topic: Nested – if Page No: 32

●Main Topic: Loops In Python Page No: 33


○ Sub Topic: While Page No: 34
○ Sub Topic: For Page No: 35
● Main Topic: Function in Python Page No: 36
○ Sub Topic: Types of Function Page No: 36
1
○ Sub Topic: Types of Function argument Page No: 38
○ Sub Topic: Packing & Unpacking Page No: 41

Main Topic: OOP Page No: 44


 Sub Topic: Inheritance Page No: 44
 Sub Topic: Constructor Chaining Page No: 51
 Sub Topic: Method Chaining Page No: 52
 Sub Topic: Polymorphism Page No: 55
 Sub Topic: Encapsulation Page No: 60
 Sub Topic: Abstraction Page No: 62

Main Topic:Advanced Python Page No: 65


 Sub Topic: Lambda Function Page No: 65
 Sub Topic:Map Function Page No: 66
 Sub Topic: Filter Function Page No: 67
 Sub Topic: Comprehension Page No: 68
 Sub Topic: File Handling Page No: 73
 Sub Topic: Exception Handling Page No: 80
 Sub Topic : Iterator Page No:87
 Sub Topic : Generator Page No:88
 Sub Topic : Decorator Page No:90

Main Topic : Introduction to Python


Define :

2
Python is a widely used general-purpose, high level programming language. It was initially
designed by Guido van Rossum in 1991 and developed by Python Software Foundation. It
was mainly developed for emphasis on code readability, and its syntax allows programmers
to express concepts in fewer lines of code. Python is a programming language that lets you
work quickly and integrate systems more efficiently.

There are two major Python versions- Python 2 and Python 3. • On 16 October 2000,
Python 2.0 was released with many new features. • On 3rd December 2008, Python 3.0 was
released with more testing and includes new features.

Sub-Topic : Features of Python


Python is a popular high-level programming language known for its simplicity and versatility. Here
are some key features:

1. Easy to Learn and Use


 Python has a simple and clean syntax, making it beginner-friendly.

2. Interpreted Language
 Python does not require compilation; it is executed line by line.

3. Dynamically Typed
 No need to specify variable types; Python determines them at runtime.

4. Object-Oriented and Functional


 Supports object-oriented, functional, and procedural programming paradigms.

5. Extensive Standard Library


 Comes with a rich set of built-in modules and functions.

6. Platform-Independent
 Python code runs on various operating systems (Windows, Linux, macOS) without
modification.

7. Garbage Collection
 Has automatic memory management to free unused memory.

8. Highly Extensible
 Can integrate with C, C++, Java, and other languages.

9. Huge Community Support


 Large community and extensive documentation.

10. Supports Multi-threading


 Enables concurrent execution for better performance.

11. Built-in Data Structures


 Provides lists, tuples, sets, and dictionaries for efficient data handling.

3
12. Machine Learning & AI
 Popular in AI, ML, and data science with libraries like TensorFlow, NumPy, and
Pandas.
Working with Python Python Code Execution:
Python’s traditional runtime execution model: Source code you type is translated to byte
code, which is then run by the Python Virtual Machine (PVM). Your code is automatically
compiled, but then it is interpreted.

There are two modes for using the Python interpreter:


• Interactive Mode
• Script Mode

Sub-Topic : Keywords

Keywords in Python are reserved words that have special meanings and cannot be
used as variable names, function names, or identifiers. These words define the syntax
and structure of the Python language.

We can use them ,but we can not modify in their original task that they perform
There are 35 keywords present in python

import Keyword in Python


The import keyword in Python is used to bring external modules (built-in or third-
party) into a program, allowing access to additional functions and tools.
If we want list of keywords
[Link] in Python
The keyword module in Python provides a list of all reserved keywords in the
language. The [Link] attribute returns this list.

4
What is a Variable in Python?
A variable in Python is a name that stores a value. It acts as a container that holds data, which can
be changed during the program execution.

Sub-Topic : Variable

1. Declaring a Variable
In Python, you don’t need to declare the type of a variable explicitly. Simply assign a value:
x = 10 # Integer
name = "Alice" # String
pi = 3.14 # Float
is_active = True # Boolean

Variable Naming Rules


 Must start with a letter (A-Z or a-z) or an underscore _
 Cannot start with a number
 Can contain letters, numbers, and underscores (_)
 Case-sensitive (myVar and myvar are different)
 Cannot use Python keywords (if, import, for, etc.)

Global and Local Variables


 Local Variable: Defined inside a function, accessible only within that function.
 Global Variable: Defined outside a function, accessible throughout the program.

Main Topic : Data Types

Data Types in Python


A data type defines the kind of value a variable can hold. Python is dynamically
typed, meaning you don’t need to declare the type explicitly—Python assigns it
based on the value.

Sub-Topic : Single Data Types

5
Single Data Types in Python
A single data type in Python refers to a data type that holds a single value rather than multiple
values

1. Single Data Types in Python


Python has the following single-value data types:

Data Type Example Description


int x = 10 Integer (whole number)
float y = 3.14 Decimal number (floating point)
complex z = 2 + 3j Complex numbers (real + imaginary)
bool flag = True Boolean (True or False)

A. Integer (int)
Int: Int, or integer, is a whole number, positive or negative, without decimals, of
unlimited length.
x = 100
print(type(x)) # Output: <class 'int'>

B. Float (float)
Float, or "floating point number" is a number, positive or negative, containing one or
more decimals.
y = 3.14
print(type(y)) # Output: <class 'float'>

C. Complex (complex)
Stores complex numbers with real and imaginary parts.

z = 2 + 3j
print(type(z)) # Output: <class 'complex'>

D. Boolean (bool)
Stores True or False values.

flag = True
print(type(flag)) # Output: <class 'bool'>

6
Sub-Topic : Multi Data Types

1. Multi-Value Data Types in Python


Data Type Example Description
Ordered, mutable (changeable)
List (list) [1, 2, 3]
collection
Ordered, immutable (unchangeable)
Tuple (tuple) (1, 2, 3)
collection
Set (set) {1, 2, 3} Unordered, unique values
String (str) name=’aditya’ Mutable
Dictionary (dict) {"name": "Alice", "age": 25} Key-value pairs

Sub-Topic : String

A string in Python is a sequence of characters enclosed in single (' '), double (" "), or
triple (''' ''' or """ """) quotes. Strings are immutable, meaning they cannot be changed
after creation.
Example:

name = "Alice"
greeting = 'Hello, World!'
multiline = """This is
a multi-line string."""

Important Built-in String Functions in Python

Python provides many built-in functions to manipulate and process strings.

1. String Case Methods


Function Description Example
upper() Converts to uppercase "hello".upper() → 'HELLO'
lower() Converts to lowercase "HELLO".lower() → 'hello'
title() Converts to title case "hello world".title() → 'Hello World'
capitalize() Capitalizes the first letter "hello".capitalize() → 'Hello'

7
Function Description Example
Swaps
swapcase() "HeLLo".swapcase() → 'hEllO'
uppercase/lowercase

2. String Modification Methods


Function Description Example
Removes leading & trailing
strip() " hello ".strip() → 'hello'
spaces
lstrip() Removes spaces from the left " hello".lstrip() → 'hello'
Removes spaces from the
rstrip() "hello ".rstrip() → 'hello'
right
replace(old, new) Replaces a substring "hello".replace('l', 'x') → 'hexxo'

3. String Search and Checking


Function Description Example
Finds index of substring (returns -1 if
find(sub) "hello".find('l') → 2
not found)
index(sub) Finds index (raises error if not found) "hello".index('l') → 2
"hello".startswith('he') →
startswith(sub) Checks if string starts with sub
True
endswith(sub) Checks if string ends with sub "hello".endswith('o') → True
count(sub) Counts occurrences of sub "hello".count('l') → 2

4. String Splitting and Joining


Function Description Example
Splits string into a
split(delim) "hello world".split() → ['hello', 'world']
list
"hello\nworld".splitlines() → ['hello',
splitlines() Splits string by lines
'world']
Joins elements into a
join(iterable) "-".join(['hello', 'world']) → 'hello-world'
string

5. String Formatting
Function Description Example
format() Formats a string "Hello {}".format("Alice") → 'Hello Alice'
Modern string
f-strings name = "Alice"; f"Hello {name}" → 'Hello Alice'
formatting

6. String Validation Methods


Function Description Example
isdigit() Checks if string is numeric "123".isdigit() → True

8
Function Description Example
isalpha() Checks if string is alphabetic "abc".isalpha() → True
isalnum() Checks if string is alphanumeric "abc123".isalnum() → True
isspace() Checks if string contains only spaces " ".isspace() → True

Summary
Concept Explanation
What is a String? A sequence of characters in quotes (' ', " ", ''' ''')
Memory Allocation Uses string interning to store identical strings efficiently
Immutability Strings cannot be modified, only replaced
Key Functions upper(), lower(), strip(), find(), split(), join(), format()

What is Indexing in Strings?

Indexing refers to accessing individual characters in a string using their position (index).
 Python uses zero-based indexing:
 The first character is at index 0.
 The last character is at index -1.
Example:

text = "Python"
print(text[0]) # Output: 'P'
print(text[3]) # Output: 'h'
print(text[-1]) # Output: 'n' (Last character)

Syntax of Slicing:

string[start:end:step]

 start: Starting index (default is 0).


 end: Ending index (exclusive).
 step: Step size (optional, default is 1).

Examples:

text = "Hello, World!"

9
print(text[0:5]) # 'Hello' (Characters from index 0 to 4)
print(text[:5]) # 'Hello' (Start is optional)
print(text[7:]) # 'World!' (End is optional)
print(text[::2]) # 'Hlo ol!' (Every second character)
print(text[::-1]) # '!dlroW ,olleH' (Reversed string)

What is Slicing in Strings?

Slicing is used to extract a substring from a string using the colon (:) operator.
Finding the Length of a String

Use the len() function:

text = "Python"
print(len(text)) # Output: 6

Sub-Topic : List

A list in Python is an ordered, mutable (changeable) collection of elements. Lists can


store multiple data types, including integers, floats, strings, and even other lists.
Example:

my_list = [10, 20, 30, "hello", 3.14]


print(my_list) # Output: [10, 20, 30, 'hello', 3.14]

Important Built-in List Functions


Python provides various functions to manipulate lists efficiently.
1. Adding Elements to a List
Function Description Example
append(x) Adds x to the end of the list [Link](100)
insert(i, x) Inserts x at index i [Link](1, 50)
Adds all elements from
extend(iterable) [Link]([4, 5])
iterable
Examples:

lst = [10, 20, 30]

[Link](40) # [10, 20, 30, 40]


10
[Link](1, 15) # [10, 15, 20, 30, 40]
[Link]([50, 60]) # [10, 15, 20, 30, 40, 50, 60]

print(lst)

2. Removing Elements from a List


Function Description Example
remove(x) Removes the first occurrence of x [Link](20)
Removes element at index i (default:
pop(i) [Link](1)
last)
clear() Removes all elements from the list [Link]()
Examples:
lst = [10, 20, 30, 40, 50]
[Link](30) # [10, 20, 40, 50]
[Link](1) # Removes index 1 → [10, 40, 50]
[Link]() # Removes last element → [10, 40]
print(lst)

3. Finding the Length of a List


Function Description Example
Returns the number of elements in
len(lst) len(lst)
the list
Example:

lst = [10, 20, 30, 40, 50]


print(len(lst)) # Output: 5

4. Sorting and Reversing a List


Function Description Example
Sorts the list in ascending
sort() [Link]()
order
Sorts the list in descending
sort(reverse=True) [Link](reverse=True)
order
reverse() Reverses the list order [Link]()

11
Example:

numbers = [5, 2, 9, 1, 7]

[Link]() # [1, 2, 5, 7, 9]
[Link](reverse=True) # [9, 7, 5, 2, 1]
[Link]() # [1, 5, 9, 2, 7] (reverse without sorting)

print(numbers)

5. Searching in a List
Function Description Example
index(x) Returns the first index of x [Link](30)
Returns the count of x in the
count(x) [Link](10)
list
Example:

lst = [10, 20, 30, 40, 10, 20, 10]

print([Link](30)) # Output: 2
print([Link](10)) # Output: 3

6. Copying a List
Function Description Example
Creates a shallow copy of the
copy() new_lst = [Link]()
list
Example:

original = [1, 2, 3]
copy_list = [Link]()

print(copy_list) # Output: [1, 2, 3]

12
Summary Table
Operation Function Example
Add Element append(x), insert(i, x), extend(iterable) [Link](10)
Remove
remove(x), pop(i), clear() [Link](1)
Element
Find Length len(lst) len(lst)
Sort & Reverse sort(), reverse() [Link]()
Search Element index(x), count(x) [Link](30)
Copy List copy() [Link]()

Sub-Topic : Tuple

A tuple is an immutable, ordered collection of elements in Python.


 Immutable: Once created, you cannot modify (add, remove, or change) elements.
 Ordered: Elements are stored in a defined sequence.
 Can store different data types: Tuples can hold integers, strings, lists, and even
other tuples.
Example:

my_tuple = (10, 20, 30, "Hello", 3.14)


print(my_tuple) # Output: (10, 20, 30, 'Hello', 3.14)

Creating Tuples
1. Using Parentheses ()

tuple1 = (1, 2, 3, 4)

2. Without Parentheses (Tuple Packing)

tuple2 = 10, 20, 30


print(tuple2) # Output: (10, 20, 30)

3. Creating a Tuple with One Element


✅You must include a comma after the element.

single_element_tuple = (10,)
print(type(single_element_tuple)) # Output: <class 'tuple'>
13
Tuple Indexing and Slicing
1. Accessing Elements (Indexing)
Tuples use zero-based indexing.

my_tuple = (10, 20, 30, 40)


print(my_tuple[1]) # Output: 20
print(my_tuple[-1]) # Output: 40 (last element)

2. Extracting Multiple Elements (Slicing)

my_tuple = (10, 20, 30, 40, 50)


print(my_tuple[1:4]) # Output: (20, 30, 40) (excludes index 4)
print(my_tuple[:3]) # Output: (10, 20, 30)
print(my_tuple[::2]) # Output: (10, 30, 50) (every second element)
print(my_tuple[::-1]) # Output: (50, 40, 30, 20, 10) (reversed tuple)

Important Built-in Tuple Functions


Function Description Example
len(tuple) Returns number of elements len((10, 20, 30)) → 3
Returns max value (if elements are
max(tuple) max((3, 8, 2)) → 8
comparable)
min(tuple) Returns min value min((3, 8, 2)) → 2
Returns sum of elements (if
sum(tuple) sum((1, 2, 3)) → 6
numeric)
Returns a sorted list of tuple
sorted(tuple) sorted((3, 1, 2)) → [1, 2, 3]
elements
[Link](x) Counts occurrences of x (1, 2, 2, 3).count(2) → 2

[Link](x) Returns first index of x (10, 20, 30).index(20) → 1

Sub-Topic : Set

A set is an unordered, mutable, and unindexed collection of unique elements in


Python.
✅Key Features of a Set:
 Unordered: Elements are stored in an arbitrary order.
 Mutable: You can add or remove elements.

14
 Unique Elements: Duplicates are not allowed.
 No Indexing & Slicing: Unlike lists or tuples, sets do not support indexing or slicing.

Creating a Set

my_set = {1, 2, 3, 4, 5}
print(my_set) # Output: {1, 2, 3, 4, 5}

Summary
 ✅ Set is an unordered collection of unique elements.
 ❌ No indexing or slicing in sets.
 ✅ Supports operations like union (|), intersection (&), difference (-), symmetric
difference (^).
 ✅ Efficient for membership tests (in operator).
 ✅ Useful for removing duplicates from a list.

Operations on Sets
1. Adding Elements (add(), update())
Method Description Example
add(x) Adds an element x to the set {1,2}.add(3) → {1,2,3}
update(iterable Adds multiple elements from an {1,2}.update([3,4]) →
) iterable (list, tuple, etc.) {1,2,3,4}

my_set = {1, 2, 3}
my_set.add(4)
print(my_set) # Output: {1, 2, 3, 4}

my_set.update([5, 6, 7])
print(my_set) # Output: {1, 2, 3, 4, 5, 6, 7}

2. Removing Elements (remove(), discard(), pop(), clear())


Method Description Example
Removes x, raises an error if x is not
remove(x) {1,2,3}.remove(2) → {1,3}
found
Removes x, does not raise an error if
discard(x) {1,2,3}.discard(5) → {1,2,3}
x is missing
Removes and returns a random {1,2,3}.pop() → Removes an
pop()
element arbitrary element

15
Method Description Example
clear() Removes all elements {1,2,3}.clear() → {}

my_set = {10, 20, 30, 40}

my_set.remove(20)
print(my_set) # Output: {10, 30, 40}

my_set.discard(50) # ✅ No error even though 50 is not in the set

popped_item = my_set.pop()
print(popped_item) # Output: Random element
print(my_set)

my_set.clear() # Removes all elements


print(my_set) # Output: set()

3. Set Operations (Union, Intersection, Difference, Symmetric Difference)


Operato
Method Description Example
r
Returns elements from
` ` union()
both sets
Returns common {1,2} & {2,3} →
& intersection()
elements {2}
Elements in first set but {1,2} - {2,3} →
- difference()
not in second {1}
Elements in either set, but {1,2} ^ {2,3} →
^ symmetric_difference()
not both {1,3}

A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

print(A | B) # Union → {1, 2, 3, 4, 5, 6}


print(A & B) # Intersection → {3, 4}
print(A - B) # Difference → {1, 2}
print(A ^ B) # Symmetric Difference → {1, 2, 5, 6}

16
4. Checking Subsets and Supersets
Method Description Example
Returns True if all elements of this {1,2}.issubset({1,2,3}) →
issubset(set)
set exist in another True
Returns True if this set contains all {1,2,3}.issuperset({1,2})
issuperset(set)
elements of another → True

A = {1, 2}
B = {1, 2, 3, 4}

print([Link](B)) # True
print([Link](A)) # True

5. Copying a Set (copy())


Creates a shallow copy of the set.

original_set = {1, 2, 3}
copied_set = original_set.copy()
print(copied_set) # Output: {1, 2, 3}

Important Built-in Functions in Sets


Function Description Example
len(set) Returns number of elements len({1,2,3}) → 3
max(set) Returns max value max({1,2,3}) → 3
min(set) Returns min value min({1,2,3}) → 1
sum(set) Returns sum of elements sum({1,2,3}) → 6
Returns a sorted list of set
sorted(set) sorted({3,1,2}) → [1,2,3]
elements

numbers = {10, 5, 30, 20}

print(len(numbers)) # Output: 4
print(max(numbers)) # Output: 30
print(min(numbers)) # Output: 5
print(sum(numbers)) # Output: 65

17
print(sorted(numbers)) # Output: [5, 10, 20, 30]

Sub-Topic : Dictionary

A dictionary (dict) in Python is an unordered, mutable collection of key-value


pairs. It allows for fast lookup, insertion, and deletion using keys.

✅Key Features:
 Keys must be unique and immutable (e.g., strings, numbers, tuples).
 Values can be any data type (including lists, tuples, and other dictionaries).
 Dictionaries are unordered (in Python 3.6+, they maintain insertion order).

Dictionary Indexing & Slicing


1. Dictionary Indexing
✅ Unlike lists or tuples, dictionaries use keys instead of numeric indexes.
To access values, use dict[key].

my_dict = {"name": "Alice", "age": 25, "city": "New York"}

print(my_dict["name"]) # Output: Alice


print(my_dict["age"]) # Output: 25

❌ Error if the key doesn't exist

print(my_dict["country"]) # KeyError: 'country'

✅ Use .get() to avoid errors

print(my_dict.get("country", "Not Found")) # Output: Not Found

2. Dictionary Slicing
Unlike lists or strings, dictionaries do not support traditional slicing because they are key-based
and unordered.

✅ Alternative: Slicing using Dictionary Comprehension


You can create a new dictionary from a subset of keys.

my_dict = {"a": 1, "b": 2, "c": 3, "d": 4}

# Extract keys "a" and "c"


sliced_dict = {k: my_dict[k] for k in ["a", "c"]}

18
print(sliced_dict) # Output: {'a': 1, 'c': 3}

Important Dictionary Built-in Functions


1. Adding and Updating Elements
Method Description Example
dict[key] = value Adds or updates a key-value pair d["age"] = 30
Updates a dictionary with another [Link]({"city":
update(dict2)
dictionary "Paris"})

my_dict = {"name": "Alice", "age": 25}

# Adding a new key-value pair


my_dict["city"] = "New York"
print(my_dict) # {'name': 'Alice', 'age': 25, 'city': 'New York'}

# Updating an existing key


my_dict["age"] = 30
print(my_dict) # {'name': 'Alice', 'age': 30, 'city': 'New York'}

# Using update()
my_dict.update({"country": "USA", "age": 31})
print(my_dict) # {'name': 'Alice', 'age': 31, 'city': 'New York',
'country': 'USA'}

2. Removing Elements
Method Description Example
pop(key) Removes key and returns value [Link]("age")
Removes the last inserted key-value
pop-item() [Link]()
pair
del d[key] Deletes a specific key del d["name"]
clear() Removes all items from the dictionary [Link]()

my_dict = {"name": "Alice", "age": 25, "city": "New York"}

# Remove key-value pair using pop()


removed_value = my_dict.pop("age")
print(removed_value) # Output: 25

19
print(my_dict) # {'name': 'Alice', 'city': 'New York'}

# Remove last inserted item using popitem()


my_dict.popitem()
print(my_dict) # {'name': 'Alice'}

# Deleting a key
del my_dict["name"]
print(my_dict) # {}

# Clearing all elements


my_dict.clear()
print(my_dict) # {}

3. Retrieving Dictionary Keys, Values, and Items


Method Description Example
Returns a list-like view of
keys() [Link]() → dict_keys(['name', 'age'])
dictionary keys
Returns a list-like view of
values() [Link]() → dict_values(['Alice', 25])
dictionary values
Returns a list-like view of [Link]() → dict_items([('name',
items()
key-value pairs 'Alice'), ('age', 25)])

my_dict = {"name": "Alice", "age": 25, "city": "New York"}

print(my_dict.keys()) # dict_keys(['name', 'age', 'city'])


print(my_dict.values()) # dict_values(['Alice', 25, 'New York'])
print(my_dict.items()) # dict_items([('name', 'Alice'), ('age', 25),
('city', 'New York')])

✅You can convert these views to lists:

keys_list = list(my_dict.keys()) # ['name', 'age', 'city']


values_list = list(my_dict.values()) # ['Alice', 25, 'New York']
items_list = list(my_dict.items()) # [('name', 'Alice'), ('age', 25),
('city', 'New York')]

4. Checking if a Key Exists (in operator)

20
my_dict = {"name": "Alice", "age": 25}

print("name" in my_dict) # True


print("city" in my_dict) # False

5. Copying a Dictionary
Method Description Example
Returns a shallow copy of the
copy() new_dict = old_dict.copy()
dictionary

original = {"a": 1, "b": 2}


copy_dict = [Link]()

print(copy_dict) # {'a': 1, 'b': 2}

6. Default Values (get() and setdefault())


Method Description Example
Returns value if key exists, else
get(key, default) [Link]("age", 0)
default
Returns value if key exists;
set-default(key, [Link]("city",
otherwise, inserts the key with the
default) default value "Unknown")

my_dict = {"name": "Alice", "age": 25}

print(my_dict.get("city", "Not Found")) # Output: Not Found


print(my_dict.setdefault("city", "Unknown")) # Adds "city": "Unknown"
print(my_dict) # {'name': 'Alice', 'age': 25, 'city': 'Unknown'}

7. Sorting a Dictionary
Method Description Example
sorted(dict) Returns sorted keys sorted(d)
Returns sorted (key, value)
sorted([Link]()) sorted([Link]())
pairs

21
my_dict = {"b": 2, "c": 3, "a": 1}

print(sorted(my_dict)) # ['a', 'b', 'c']


print(sorted(my_dict.items())) # [('a', 1), ('b', 2), ('c', 3)]

Sub-Topic : Copy Operation

Copying objects in Python is important for preserving data integrity and managing
memory efficiently. Python provides multiple ways to copy objects, and each type of
copy affects memory allocation differently.
There are three main types of copy operations:
1. Normal Assignment (Reference Copy)
2. Shallow Copy ([Link]())
3. Deep Copy ([Link]())

1. Normal Copy (Assignment =) – No Actual Copy


When you use = to assign a variable to another, no new object is created. Instead,
both variables refer to the same memory location.
Example: Reference Copy

original_list = [1, 2, 3]
referenced_list = original_list # No copy, just a reference

referenced_list[0] = 99

print(original_list) # [99, 2, 3]
print(referenced_list) # [99, 2, 3]

🚨 Both lists share the same memory—changes affect both variables.


Memory Allocation in Assignment (=)
 No new object is created.
 Both variables point to the same memory address.
 Any modification in one variable affects the other.

22
2. Shallow Copy ([Link]())
A shallow copy creates a new outer object, but does not create new copies of
nested objects. Instead, the nested objects still reference the original memory
location.
Example: Shallow Copy

import copy

original_list = [[1, 2, 3], [4, 5, 6]]


shallow_copied_list = [Link](original_list)

# Modify nested object


shallow_copied_list[0][0] = 99

print(original_list) # [[99, 2, 3], [4, 5, 6]]


print(shallow_copied_list) # [[99, 2, 3], [4, 5, 6]]

✅ New object is created, but references to nested lists remain shared.


Memory Allocation in Shallow Copy
 The outer object (list) gets a new memory address.
 The inner objects (nested lists) share the same memory address as the
original.
 Changes made to nested objects reflect in both original and copied objects.

3. Deep Copy ([Link]())


A deep copy creates a completely independent copy of an object, including all
nested objects. Modifications in the copied object will not affect the original.
Example: Deep Copy

import copy

original_list = [[1, 2, 3], [4, 5, 6]]


deep_copied_list = [Link](original_list)

# Modify nested object


deep_copied_list[0][0] = 99

23
print(original_list) # [[1, 2, 3], [4, 5, 6]]
print(deep_copied_list) # [[99, 2, 3], [4, 5, 6]]

✅ Completely new memory allocation for all objects, including nested structures.
Memory Allocation in Deep Copy
 The outer object gets a new memory address.
 All inner objects (nested elements) also get new memory addresses.
 Changes made in the deep-copied object do not affect the original object.

Comparison Table: Copy Types & Memory Allocation


Effect on Effect on
Copy Type Outer Nested Memory Allocation
Object Objects
No new
Assignment (=) No new object Same memory for everything
object
New memory for outer object,
Shallow Copy New outer Shared nested
shared memory for nested
([Link]()) object objects
objects
Deep Copy New outer New nested
New memory for everything
([Link]()) object objects

Key Takeaways
1. Use = when you want a reference to the same object.
2. Use [Link]() for a shallow copy (outer object is new, but nested objects
are shared).
3. Use [Link]() for a full, independent copy (both outer and inner
objects are new).

Main Topic : Operator

Understanding Operator, Operand, and Operation in Python


In programming, operators, operands, and operations are fundamental concepts
used to perform calculations, comparisons, and logical manipulations.

24
1. Operator
An operator is a symbol that tells the program to perform a specific mathematical,
relational, or logical computation.
Examples of Operators in Python:
 Arithmetic Operators: +, -, *, /
 Comparison Operators: >, <, ==, !=
 Logical Operators: and, or, not
 Bitwise Operators: &, |, ^
 Assignment Operators: =, +=, -=, *=

2. Operand
An operand is a value or variable on which an operator performs an operation.
Example:

a = 10
b = 5
c = a + b # '+' is the operator, 'a' and 'b' are operands
print(c) # Output: 15

 Here, a and b are operands, and + is the operator.

3. Operation
An operation is the process of applying an operator to operands to produce a result.
Example of an Operation:

x = 8
y = 4
result = x * y # '*' is the operator, 'x' and 'y' are operands
print(result) # Output: 32

 The operation here is multiplication (8 * 4), which produces 32.

25
1. Arithmetic Operators
These operators perform basic mathematical operations.

Operator Meaning Example (a = 10, b = 5) Output


+ Addition a + b 15
- Subtraction a - b 5
* Multiplication a * b 50
/ Division a / b 2.0
// Floor Division a // b 2
% Modulus (Remainder) a % b 0
** Exponentiation (Power) a ** b 100000

Example:

a = 10
b = 5
print(a + b) # Output: 15
print(a % b) # Output: 0
print(a ** b) # Output: 100000

2. Assignment Operators
Used to assign values to variables.

Operator Meaning Example (a = 10) Equivalent To


= Assign a = 10 a = 10
+= Add and Assign a += 5 a = a + 5
-= Subtract and Assign a -= 3 a = a - 3
*= Multiply and Assign a *= 2 a = a * 2
/= Divide and Assign a /= 2 a = a / 2
//= Floor Divide and Assign a //= 3 a = a // 3
%= Modulus and Assign a %= 3 a = a % 3
**= Exponentiation and Assign a **= 2 a = a ** 2

Example:

x = 10
x += 5 # Same as x = x + 5
print(x) # Output: 15

3. Comparison (Relational) Operators


Used to compare values and return True or False.

26
Operator Meaning Example (a = 10, b = 5) Output
== Equal to a == b False
!= Not equal to a != b True
> Greater than a > b True
< Less than a < b False
>= Greater or equal a >= b True
<= Less or equal a <= b False

Example:

a = 10
b = 5
print(a > b) # Output: True
print(a == b) # Output: False

4. Logical Operators
Used to combine conditional statements.

Operator Meaning Example (a = True, b = False) Output


and Returns True if both conditions are True a and b False
Returns True if at least one condition is
or a or b True
True
not Reverses the boolean value not a False

Example:

x = True
y = False
print(x and y) # Output: False
print(x or y) # Output: True
print(not x) # Output: False

5. Bitwise Operators
Used for binary (bit-level) operations.

Operator Meaning Example (a = 5 (101), b = 3 (011)) Output


& AND a & b (101 & 011) 1
` ` OR `a
^ XOR a ^ b (101 ^ 011) 6
~ NOT ~a (~101) -6
<< Left Shift a << 1 (1010) 10
>> Right Shift a >> 1 (10) 2

27
Example:

a = 5 # Binary: 101
b = 3 # Binary: 011

print(a & b) # Output: 1 (Binary: 001)


print(a | b) # Output: 7 (Binary: 111)
print(a ^ b) # Output: 6 (Binary: 110)
print(~a) # Output: -6 (Binary: -110)

6. Identity Operators (is, is not)


Used to check if two variables refer to the same memory location.

Example (a = [1, 2, 3], b = a, c


Operator Meaning Output
= [1, 2, 3])
Returns True if both variables point
is a is b True
to the same object
Returns True if both variables point
is not a is not c True
to different objects

Example:

a = [1, 2, 3]
b = a # Same reference
c = [1, 2, 3] # Different object

print(a is b) # Output: True


print(a is not c) # Output: True

7. Membership Operators (in, not in)


Used to check whether a value exists in a sequence (like lists, tuples, strings).

Operator Meaning Example (list1 = [1, 2, 3]) Output


in Returns True if the value is in the sequence 2 in list1 True
Returns True if the value is not in the
not in 5 not in list1 True
sequence

Example:

my_list = [10, 20, 30, 40]


print(20 in my_list) # Output: True
print(50 not in my_list) # Output: True

28
Conclusion
Python provides a variety of operators to perform different types of computations and logical
operations. Here’s a quick summary:

 Arithmetic Operators (+, -, *, /, //, %, **) – Used for mathematical calculations.


 Assignment Operators (=, +=, -=, *=, /=, //=, %=) – Assign values to variables.
 Comparison Operators (==, !=, >, <, >=, <=) – Compare values.
 Logical Operators (and, or, not) – Used in conditional statements.
 Bitwise Operators (&, |, ^, ~, <<, >>) – Work at the binary level.
 Identity Operators (is, is not) – Check if variables refer to the same object.
 Membership Operators (in, not in) – Check if a value exists in a sequence.

Main Topic : Conditional Statement

Python provides three types of conditional statements:


1. if statement
2. if-else statement
3. if-elif-else statement
4. Nested if statement

Sub-Topic : if Statement

29
1. if Statement
✅The if statement executes a block of code if the
given condition is True.
❌ If the condition is False, it skips the block.
Syntax:

if condition:
# Code to execute when condition is
True

Example:

age = 18
if age >= 18:
print("You are eligible to vote.")

2. if-else Statement
✅The if-else statement executes one block if the
condition is True and another block if the condition is
False.

Syntax:

if condition:
# Code if condition is True
else:
# Code if condition is False

Example:

age = 16
if age >= 18:
print("You are eligible to vote.")
else:
print("You are not eligible to vote.")

Flowchart:

30
3. if-elif-else Statement (Multiple Conditions)
✅The if-elif-else statement allows checking multiple conditions one by one.
🚨 If one elif condition is True, it executes that block and skips the rest.
❌ If no conditions are True, the else block
runs.

Syntax:

if condition1:
# Code if condition1 is True
elif condition2:
# Code if condition2 is True
elif condition3:
# Code if condition3 is True
else:
# Code if all conditions are False

Example:

marks = 75

if marks >= 90:


print("Grade: A")
elif marks >= 75:
print("Grade: B")
elif marks >= 50:
print("Grade: C")
else:
print("Grade: F")

4. Nested if Statement
✅A nested if statement means if conditions inside another if condition.
🚨 The inner if condition only checks if the outer condition is True.

31
Syntax:

if condition1:
if condition2:
# Code if both conditions are True
else:
# Code if condition1 is True but condition2 is
False
else:
# Code if condition1 is False

Example:

age = 20
citizen = "Yes"

if age >= 18:


if citizen == "Yes":
print("You are eligible to vote.")
else:
print("You must be a citizen to vote.")
else:
print("You are not old enough to vote.")

Summary Table
Conditional
Description Example
Statement
Executes code if condition
if if x > 10: print("Big number")
is True
Executes one block if if x > 10: print("Big") else:
if-else
True, another if False print("Small")
Checks multiple conditions if x > 90: print("A") elif x > 75:
if-elif-else
one by one print("B") else: print("F")
Nested if if inside another if if x > 10: if y > 5: print("Valid")

Main Topic : Loops in Python

Loops in Python
A loop is a programming construct that repeats a block of code multiple times until a condition is
met. Python provides two types of loops:
1. for loop
2. while loop

32
1🚨 for Loop
✅The for loop is used to iterate over a sequence (list, tuple, string, etc.).
🚨 It runs for a fixed number of iterations.

Syntax:

for variable in sequence:


# Code block to execute

Example:

for i in range(5): # Loops 5 times (0 to 4)


print("Iteration:", i)

Flowchart of for Loop

Start
|
Initialize Loop Variable
|
Check Condition (Sequence)
|
+----+----+
| Yes |
v v
Execute Exit Loop
Block (No More Items)
|
Increment / Next Item
|
|
Repeat

2🚨 while Loop
✅The while loop runs as long as the condition is True.
🚨 It is used when the number of iterations is unknown beforehand.

Syntax:

while condition:
# Code block to execute

Example:

33
count = 0
while count < 5: # Runs until count reaches 5
print("Count:", count)
count += 1

Flowchart of while Loop

Start
|
Check Condition
|
+----+----+
| True |
v v
Execute Exit Loop
Block (Condition False)
|
Increment / Update
|
|
Repeat

Difference Between for and while Loop


Feature for Loop while Loop
Use Case When number of iterations is known When iterations depend on a condition
Example for i in range(5): print(i) while i < 5: print(i)
Condition Iterates over a sequence Checks condition each time

Nested Loops
✅A loop inside another loop is called a nested loop.
✅ It is useful for working with tables, matrices, or patterns.

Example:

for i in range(3): # Outer loop


for j in range(2): # Inner loop
print(f"i={i}, j={j}")

Loop Control Statements


Python provides special statements to control loops:
1. break → Stops the loop completely.
2. continue → Skips the current iteration & moves to the next.
3. pass → Placeholder that does nothing.

34
Example:

for i in range(5):
if i == 3:
break # Stops when i = 3
print(i) # Output: 0, 1, 2

Conclusion
✅ Loops automate repetitive tasks, making code efficient.
✅ for loops iterate over sequences, while loops run until a condition is False.
✅ Flowcharts help visualize how loops work.

Main Topic : Function in Python

In Python, a function is a reusable block of code that performs a


specific task. Functions help in organizing and modularizing
code, making it easier to read, debug, and maintain.
Sub-Topic : Types of Functions in Python
Python has several types of functions:

1. Built-in Functions
These are pre-defined functions in Python that can be used directly. Examples:

print("Hello, World!") # Prints output to the console


len([1, 2, 3]) # Returns length of the list
max(10, 20) # Returns the maximum value

2. User-Defined Functions
These are functions created by the user using the def keyword. Example:

def greet(name):
return f"Hello, {name}!"

print(greet("Alice"))

Function declaration types

1. Function with Parameters and Return Value


 Takes arguments (parameters).

35
 Returns a value using the return statement.

Syntax:

def function_name(param1, param2):


# Function logic
return result

Example:

def add(a, b):


return a + b

print(add(5, 3)) # Output: 8

✅ Best for calculations and reusable logic.

2. Function with Parameters but Without Return Value


 Takes arguments.
 Performs an action but does not return a value (return is optional).

Syntax:

def function_name(param1, param2):


# Function logic

Example:

def greet(name):
print(f"Hello, {name}!")

greet("Alice") # Output: Hello, Alice!

✅ Used for operations like printing, logging, or modifying global variables.

3. Function Without Parameters but With Return Value


 Takes no arguments.
 Returns a value.
Syntax:

def function_name():
# Function logic
return result

Example:

36
def get_pi():
return 3.14159

print(get_pi()) # Output: 3.14159

✅ Used when a function always returns the same result without needing input.

4. Function Without Parameters and Without Return Value


 Takes no arguments.
 Performs an action but does not return a value.
Syntax:

def function_name():
# Function logic

Example:

def greet():
print("Hello, World!")

greet() # Output: Hello, World!

✅ Used for simple actions like printing messages.

Sub-Topic : Types of Function argument

In Python, function arguments can be categorized into different


types based on how they are passed to functions. Here are the
main types:

1. Positional Arguments
Arguments that are passed in order and must match the function parameters in the same sequence.
Example:

def greet(name, age):


print(f"Hello, my name is {name} and I am {age} years old.")

greet("Alice", 25) # Output: Hello, my name is Alice and I am 25 years old.

✅ Order matters in positional arguments.

37
2. Default Arguments
Arguments that have default values. If no value is provided, the default value is used.
Example:

def greet(name, age=18):


print(f"Hello, my name is {name} and I am {age} years old.")

greet("Bob") # Output: Hello, my name is Bob and I am 18 years old.


greet("Alice", 25) # Output: Hello, my name is Alice and I am 25 years old.

✅ Default arguments must come after required (positional) arguments.

3. Keyword Arguments
Arguments that are passed with parameter names, allowing flexibility in order.
Example:

def greet(name, age):


print(f"Hello, my name is {name} and I am {age} years old.")

greet(age=30, name="Charlie") # Output: Hello, my name is Charlie and I am 30 years old.

✅ Order doesn’t matter when using keyword arguments.

4. Variable-Length Arguments (*args)


Used when you don't know how many positional arguments will be passed.
Example:

def add_numbers(*args):
return sum(args)

print(add_numbers(1, 2, 3)) # Output: 6


print(add_numbers(5, 10, 15, 20)) # Output: 50

✅ *args collects multiple arguments into a tuple.

5. Variable-Length Keyword Arguments (**kwargs)


Used when you don’t know how many keyword arguments will be passed.
Example:

38
def student_info(**kwargs):
for key, value in [Link]():
print(f"{key}: {value}")

student_info(name="David", age=22, course="Python")


# Output:
# name: David
# age: 22
# course: Python

✅ **kwargs collects multiple keyword arguments into a dictionary.

6. Positional-Only Arguments (/)


Introduced in Python 3.8+, these arguments must be passed positionally and cannot be used as
keyword arguments.
Example:

def multiply(a, b, /):


return a * b

print(multiply(2, 3)) # ✅ Works


# print(multiply(a=2, b=3)) ❌ Throws error

✅The / before an argument list marks them as positional-only.

7. Keyword-Only Arguments (*)


These arguments must be passed using keywords (not positionally).
Example:

def divide(a, *, b):


return a / b

print(divide(10, b=2)) # ✅ Works


# print(divide(10, 2)) ❌ Throws error

✅The * before an argument list marks them as keyword-only.

8. Combination of Arguments
You can mix different types of arguments, but the order should be:

Positional → Default → *args → Keyword-only → **kwargs

Example:

39
def example(a, b=2, *args, c=3, **kwargs):
print(f"a: {a}, b: {b}, args: {args}, c: {c}, kwargs: {kwargs}")

example(1, 5, 10, 20, c=15, x=100, y=200)


# Output: a: 1, b: 5, args: (10, 20), c: 15, kwargs: {'x': 100, 'y': 200}

Summary Table
Argument Type Syntax Description
Positional func(a, b) Must be passed in order
Default func(a, b=10) Has default values if not provided
Keyword func(a=10, b=20) Passed using parameter names
Accepts multiple positional
Variable-Length (*args) func(*args)
arguments
Variable-Length Keyword Accepts multiple keyword
func(**kwargs)
(**kwargs) arguments
Positional-Only (/) func(a, b, /) Must be passed as positional
Keyword-Only (*) func(a, *, b) Must be passed as keyword

Sub-Topic : Packing & Unpacking

Packing and Unpacking in Python


Packing and unpacking are concepts related to handling multiple values in Python, especially when
dealing with functions, tuples, lists, and dictionaries.

1. Packing
Packing means grouping multiple values into a single variable (usually as a tuple, list, or
dictionary).

Tuple Packing
When multiple values are assigned to a single variable, Python automatically packs them into a
tuple.
Example:

data = 10, 20, 30 # Tuple packing


print(data) # Output: (10, 20, 30)

List Packing
A list can also be packed explicitly:
Example:

40
data = [1, 2, 3, 4, 5] # List packing
print(data) # Output: [1, 2, 3, 4, 5]

Dictionary Packing (**kwargs)


When using **kwargs in functions, multiple keyword arguments get packed into a dictionary.

Example:

def student_info(**kwargs):
print(kwargs)

student_info(name="Alice", age=22, course="Python")


# Output: {'name': 'Alice', 'age': 22, 'course': 'Python'}

✅ Packing is useful when we don’t know how many values will be passed.

2. Unpacking
Unpacking means extracting values from a packed variable into individual variables.

Tuple Unpacking
Values from a tuple can be unpacked into individual variables.
Example:
t
data = (10, 20, 30) # Tuple
a, b, c = data # Unpacking
print(a, b, c) # Output: 10 20 30

List Unpacking
Similar to tuple unpacking but with lists.
Example:

data = [1, 2, 3]
x, y, z = data
print(x, y, z) # Output: 1 2 3

Partial Unpacking Using * Operator


You can use * to unpack some values while storing the rest in a list.

Example:

data = (1, 2, 3, 4, 5)
a, *b, c = data
print(a) # Output: 1
print(b) # Output: [2, 3, 4]
print(c) # Output: 5

41
Dictionary Unpacking (**)
You can unpack a dictionary into function arguments.
Example:

def student(name, age):


print(f"Name: {name}, Age: {age}")

info = {"name": "Bob", "age": 23}


student(**info) # Unpacking dictionary

# Output: Name: Bob, Age: 23

✅ Unpacking is useful for easy data extraction and function argument passing.

Packing & Unpacking in Functions


Packing with *args
Used for passing multiple positional arguments.

def add_numbers(*args):
return sum(args)

print(add_numbers(1, 2, 3, 4)) # Output: 10

Unpacking with *
Used for unpacking arguments into function parameters.

def multiply(a, b, c):


return a * b * c

numbers = (2, 3, 4)
print(multiply(*numbers)) # Output: 24

Summary Table
Concept Description Example
Packing (Tuple/List) Combining multiple values into one data = (1, 2, 3)
Groups multiple function arguments
Packing (*args) def func(*args): print(args)
into a tuple
Groups multiple keyword arguments def func(**kwargs):
Packing (**kwargs)
into a dictionary print(kwargs)
Unpacking Extracting values from a packed
a, b = (10, 20)
(Tuple/List) variable
Unpacking (*) Assigns remaining values to a list a, *b, c = (1, 2, 3, 4)
Unpacking Passing dictionary values as func(**{"name": "Bob"})

42
Concept Description Example
Dictionary (**) arguments

Main Topic : OOP (object oriented Programming)

OOP (Object-Oriented Programming) in Python is a


programming paradigm that uses objects and classes to
structure code. It allows developers to model real-world
entities using attributes (data) and methods (functions) that
operate on the data.

Sub-Topic : Inheritance

1. Class
A class is a blueprint for creating objects. It defines a structure that objects follow,
including attributes (variables) and methods (functions).
Example of a Class

class Car:
def __init__(self, brand, model):
[Link] = brand # Attribute
[Link] = model # Attribute

def display_info(self): # Method


return f"{[Link]} {[Link]}"

2. Object
An object is an instance of a class. It represents a specific entity that has real values
assigned to its attributes.

my_car = Car("Toyota", "Corolla") # Object instantiation


print(my_car.display_info()) # Output: Toyota Corolla
43
Key Differences Between Class and Object
Feature Class Object
Definition Blueprint/template Instance of the class
Memory No memory
Memory allocated when created
Allocation allocation
Example Car my_car = Car("Toyota", "Corolla")

🚨 Static Method, Class Method, and Instance Method in Python


Python provides three types of methods inside a class:

1. Instance Method (self) → Works with object instance data


2. Class Method (cls) → Works with class-level data
3. Static Method (No self or cls) → Independent utility functions

1🚨 Instance Method (self)


✅Works with object instance data
✅ Can access both instance attributes and class attributes

🚨 Example:

class Dog:
def __init__(self, name):
[Link] = name # Instance Attribute

def bark(self): # Instance Method


print(f"{[Link]} says Woof!")

dog1 = Dog("Buddy")
[Link]() # Output: Buddy says Woof!

🚨 Use Case: Modify or retrieve object-specific data.

2🚨 Class Method (@classmethod, cls)


✅Works with class-level data
✅ Uses @classmethod and cls instead of self
✅ Can modify class attributes but cannot access instance attributes

🚨 Example:

class Dog:
species = "Canine" # Class Attribute

44
@classmethod
def get_species(cls):
return [Link]

print(Dog.get_species()) # Output: Canine

🚨 Use Case: When you need to work with class attributes instead of instance attributes.

3🚨 Static Method (@staticmethod)


✅ Independent utility function inside a class
✅ Uses @staticmethod (No self or cls)
✅ Cannot modify class or instance attributes

🚨 Example:

class MathUtils:
@staticmethod
def add(a, b):
return a + b

print([Link](3, 5)) # Output: 8

🚨 Use Case: Use when a function doesn’t need to access class or instance data (e.g., utility
functions).

🚨 Summary: When to Use Each Method?


Uses Uses Access Instance Access Class
Method Type Common Use Case
self? cls? Data? Data?
Instance Modify object-specific
✅Yes ❌ No ✅Yes ✅Yes
Method data
Class Method ❌ No ✅Yes ❌ No ✅Yes Modify class-level data
Utility function inside a
Static Method ❌ No ❌ No ❌ No ❌ No
class

✅ Use @staticmethod when the method does not need self or cls.
✅ Use @classmethod when working with class-level data.
✅ Use instance methods when working with object-specific data.

Inheritance means that using code again and again using the classname as it is

Inheritance is a mechanism in Object-Oriented Programming (OOP) that allows


one class to inherit the attributes and methods of another class. This promotes
code reuse and hierarchical relationships between classes.
45
Types of Inheritance in Python
1. Single Inheritance
A subclass inherits from a single parent class.

class Parent:
def func1(self):
print("This is Parent class")

class Child(Parent): # Inheriting Parent class


def func2(self):
print("This is Child class")

obj = Child()
obj.func1() # Accessing Parent class method
obj.func2()

2. Multiple Inheritance
A subclass inherits from multiple parent classes.

class Parent1:
def func1(self):
print("This is Parent1 class")

class Parent2:
def func2(self):
print("This is Parent2 class")

class Child(Parent1, Parent2): # Inheriting from both Parent1 and


Parent2
def func3(self):
print("This is Child class")

obj = Child()
obj.func1()
obj.func2()

46
obj.func3()

3. Multilevel Inheritance
A class inherits from another class, which in turn inherits from another class.

class Grandparent:
def func1(self):
print("This is Grandparent class")

class Parent(Grandparent):
def func2(self):
print("This is Parent class")

class Child(Parent):
def func3(self):
print("This is Child class")

obj = Child()
obj.func1()
obj.func2()
obj.func3()

4. Hierarchical Inheritance
Multiple child classes inherit from a single parent class.

class Parent:
def func1(self):
print("This is Parent class")

class Child1(Parent):
def func2(self):
print("This is Child1 class")

class Child2(Parent):
def func3(self):

47
print("This is Child2 class")

obj1 = Child1()
obj2 = Child2()

obj1.func1()
obj1.func2()

obj2.func1()
obj2.func3()

5. Hybrid Inheritance
A combination of two or more types of inheritance.
class A:
def func1(self):
print("This is class A")

class B(A):
def func2(self):
print("This is class B")

class C(A):
def func3(self):
print("This is class C")

class D(B, C): # Inheriting from both B and C


def func4(self):
print("This is class D")

obj = D()
obj.func1()
obj.func2()
obj.func3()
obj.func4()

48
A constructor is a special method in Python used to initialize an object when it is
created. In Python, the constructor method is named __init__() and is called
automatically when a new object of a class is instantiated.

Syntax of a Constructor

class ClassName:
def __init__(self, parameters): # Constructor
# Initialize attributes

Types of Constructors in Python


1. Default Constructor
A constructor that doesn’t take any parameters except self.

class Person:
def __init__(self): # Default constructor
print("Default Constructor Called!")

# Object creation
obj = Person()

2. Parameterized Constructor
A constructor that takes parameters to initialize object attributes.

class Person:
def __init__(self, name, age): # Parameterized constructor
[Link] = name
[Link] = age

def display(self):
print(f"Name: {[Link]}, Age: {[Link]}")

# Creating object with parameters


person1 = Person("Alice", 30)
49
[Link]()

3. Constructor with Default Values


A constructor that provides default values for parameters.

class Car:
def __init__(self, brand="Toyota", model="Corolla"):
[Link] = brand
[Link] = model

def display(self):
print(f"Car: {[Link]} {[Link]}")

# Creating objects with and without parameters


car1 = Car() # Uses default values
car2 = Car("Honda", "Civic")

[Link]() # Output: Toyota Corolla


[Link]() # Output: Honda Civic

4. Constructor Overriding
A subclass can override the constructor of its parent class.

class Parent:
def __init__(self):
print("Parent Constructor")

class Child(Parent):
def __init__(self):
super().__init__() # Calls Parent constructor
print("Child Constructor")

obj = Child()

Output:

50
Parent Constructor
Child Constructor

Key Points About Constructors


 The __init__() method is called automatically when an object is created.
 self refers to the instance of the class.
 super().__init__() is used to call the parent class constructor in case of
inheritance.

Sub-Topic : Constructor chaining

Types of Constructor Chaining Using super() in Python


Constructor chaining using super() allows a child class to call a parent class
constructor. There are two common ways to achieve this:
1. Using super() (Recommended way)
2. Using ParentClassName.__init__(self, ...) (Older method)

1. Using super() (Recommended)


This is the modern approach in Python 3+.
It automatically resolves the method resolution order (MRO) and is useful in
multiple inheritance.
Example:

class Parent:
def __init__(self, name):
[Link] = name
print("Parent Constructor Called")

class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # Calls Parent's constructor
[Link] = age
print("Child Constructor Called")

51
c = Child("Alice", 25)

Output:

Parent Constructor Called


Child Constructor Called

✅ Why use super()?


 Automatically finds the next constructor in the method resolution order
(MRO).
 Works well with multiple inheritance.

2. Using ParentClassName.__init__(self, ...) (Older method)


Before super(), we called the parent class constructor directly.
Example:

class Parent:
def __init__(self, name):
[Link] = name
print("Parent Constructor Called")

class Child(Parent):
def __init__(self, name, age):
Parent.__init__(self, name) # Explicitly calling Parent's
constructor
[Link] = age
print("Child Constructor Called")

c = Child("Bob", 30)

Output:

Parent Constructor Called


Child Constructor Called

Why Not Use This?


❌ Harder to maintain in multiple inheritance
❌ Doesn't follow MRO (Method Resolution Order)
52
Sub-Topic : Method chaining

Method Chaining in Python


Method chaining is a technique where multiple methods are called on the same object in a single
statement. It improves code readability and reduces redundancy.

Types of Method Chaining in Python


There are two main types:
1. Within the Same Class
2. Between Parent and Child Class (Using super() and [Link]())

1. Method Chaining Within the Same Class


Each method returns self, allowing further method calls in the same line.

Example:

class Car:
def start(self):
print("Car Started")
return self # Returning the same object

def accelerate(self):
print("Car is Accelerating")
return self

def stop(self):
print("Car Stopped")
return self

# Method chaining
car = Car()
[Link]().accelerate().stop()

Output:

Car Started
Car is Accelerating
Car Stopped

✅ Why use this?


 Reduces repetitive object calls.
 Improves readability.

53
2. Method Chaining Between Parent and Child Class
In inheritance, a child class can call a parent class method using:

1. super().method() (Preferred)
2. [Link](self, ...) (Older method)

Using super() (Recommended)

class Parent:
def display(self):
print("Parent Method")
return self # Allows further chaining

class Child(Parent):
def show(self):
print("Child Method")
return self

# Method chaining
obj = Child()
[Link]().show()

Output:

Parent Method
Child Method

✅ Works well with multiple inheritance.


✅ Automatically follows MRO (Method Resolution Order).

Using [Link](self, ...) (Older method)

class Parent:
def display(self):
print("Parent Method")
return self

class Child(Parent):
def show(self):
[Link](self) # Explicitly calling parent method
print("Child Method")
return self

# Method chaining
obj = Child()
[Link]()

Output:

Parent Method

54
Child Method

❌ Harder to maintain in multiple inheritance.


❌ Does not follow MRO automatically.

Sub-Topic : Polymorphism

Polymorphism in Python
Polymorphism means "many forms" and allows the same function, method, or operator to
behave differently based on the object or data type.
It is a process of performing multiple tasks using one single operator or method
Python do not support polymorphism
✅ Why Use Polymorphism?
 Code Reusability → Avoids writing duplicate code.
 Flexibility → Works with different data types & objects.
 Extensibility → Easy to add new functionality.

Types of Polymorphism in Python


1. Method Overloading → Same method name, different number/types of parameters.
2. Method Overriding → Same method name, different behavior in child class.
3. Operator Overloading → Operators (+, -, *, etc.) behave differently for objects.
4. Duck Typing → Type of object is determined by its behavior, not its class.

1. Method Overloading (Same Method, Different Arguments)


Python does not support method overloading like Java or C++, but we can achieve it using default
arguments or *args.

Example:

class Calculator:
def add(self, a, b=0, c=0): # Default values allow multiple cases
return a + b + c

calc = Calculator()
print([Link](5)) # Calls add(a)
print([Link](5, 10)) # Calls add(a, b)
print([Link](5, 10, 15)) # Calls add(a, b, c)

Output:

55
5
15
30

✅ Same method name works with different numbers of arguments.


Money Patching : It is a process of storing the previous method’s address in a variable name
to access the previous method
EX: def add(a,b):
print(a+b)
prev=add
def add(a,b,c,d):
print(a+b+c+d)
add(1,2,3,4)
prev(10,20)

2. Method Overriding (Same Method, Different Behavior in Child


Class)
A child class redefines a method from the parent class.

Example:

class Animal:
def sound(self):
print("Animals make sound")

class Dog(Animal):
def sound(self): # Overriding parent method
print("Dog barks")

class Cat(Animal):
def sound(self): # Overriding parent method
print("Cat meows")

dog = Dog()
cat = Cat()
[Link]() # Calls Dog's version
[Link]() # Calls Cat's version

Output:

Dog barks
Cat meows

✅ Child class modifies the method’s behavior.

56
3. Operator Overloading (Using __magic__ Methods)
Python allows overloading operators (+, -, *, etc.) for custom objects using special methods like
__add__(), __sub__(), etc.

Example: Overloading + Operator

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

def __add__(self, other): # Overloading "+"


return Point(self.x + other.x, self.y + other.y)

p1 = Point(2, 3)
p2 = Point(4, 5)
p3 = p1 + p2 # Calls __add__() method
print(p3.x, p3.y)

Output:

6 8

✅ Allows mathematical operators to work with user-defined objects.

Magic Methods (Dunder Methods) in Python


Magic methods, also known as dunder (double underscore) methods, are special methods in
Python that start and end with double underscores (__methodname__).
✅ Purpose of Magic Methods:

 Allow operator overloading (e.g., +, -, *, /).


 Define custom behavior for built-in functions (len(), str(), etc.).
 Enable object customization in classes.

1. Object Creation & Destruction


Method Description
__new__(cls, ...) Called to create a new instance before __init__.
__init__(self, ...) Called after __new__, initializes the object.
__del__(self) Called before an object is destroyed (not recommended for cleanup).

2. String Representation
Method Description
__str__(self) Defines str(obj), used in print(obj).
__repr__(self) Defines repr(obj), used in debugging (print([obj])).

57
Method Description
Defines custom string formatting (format(obj,
__format__(self, format_spec)
"spec")).
__bytes__(self) Defines bytes(obj), converts object to bytes.

3. Arithmetic Operator Overloading


Operator Magic Method Example Usage
+ (Addition) __add__(self, other) a + b
- (Subtraction) __sub__(self, other) a - b
* (Multiplication) __mul__(self, other) a * b
/ (True Division) __truediv__(self, other) a / b
// (Floor Division) __floordiv__(self, other) a // b
% (Modulo) __mod__(self, other) a % b
** (Exponentiation) __pow__(self, other) a ** b

4. In-Place Arithmetic Operators


Operator Magic Method Example Usage
+= (Addition) __iadd__(self, other) a += b
-= (Subtraction) __isub__(self, other) a -= b
*= (Multiplication) __imul__(self, other) a *= b
/= (Division) __itruediv__(self, other) a /= b
//= (Floor Division) __ifloordiv__(self, other) a //= b
%= (Modulo) __imod__(self, other) a %= b
**= (Exponentiation) __ipow__(self, other) a **= b

5. Comparison Operators
Operator Magic Method Example Usage
== (Equal) __eq__(self, other) a == b
!= (Not Equal) __ne__(self, other) a != b
< (Less Than) __lt__(self, other) a < b
<= (Less Than or Equal) __le__(self, other) a <= b
> (Greater Than) __gt__(self, other) a > b
>= (Greater Than or Equal) __ge__(self, other) a >= b

6. Bitwise Operator Overloading


Operator Magic Method Example Usage
& (Bitwise AND) __and__(self, other) a & b

58
Operator Magic Method Example Usage
` ` (Bitwise OR) __or__(self, other)
^ (Bitwise XOR) __xor__(self, other) a ^ b
<< (Left Shift) __lshift__(self, other) a << b
>> (Right Shift) __rshift__(self, other) a >> b
~ (Bitwise NOT) __invert__(self) ~a

7. Attribute Access
Method Description
__getattr__(self, name) Called when an attribute is not found in an object.
__setattr__(self, name, value) Called when an attribute is set on an object.
__delattr__(self, name) Called when an attribute is deleted from an object.

8. Container & Sequence Protocol


Method Description
__len__(self) Defines len(obj), returns object length.
__getitem__(self, index) Enables obj[index] indexing.
__setitem__(self, index, value) Enables obj[index] = value assignment.
__delitem__(self, index) Enables del obj[index].
__contains__(self, item) Enables item in obj.

9. Iteration & Looping


Method Description
__iter__(self) Returns an iterator for an object (for loops).
__next__(self) Defines behavior for next(obj).

10. Callable Objects


Method Description
__call__(self, *args, **kwargs) Makes an object callable like a function.

11. Context Managers (with Statement)


Method Description
Defines behavior when entering with
__enter__(self)
block.
Defines cleanup when leaving with
__exit__(self, exc_type, exc_value, traceback)
block.

59
Sub-Topic : Encapsulation

Encapsulation in Python
Encapsulation is one of the core OOP (Object-Oriented Programming) principles in Python.
It means restricting direct access to object data and allowing controlled access through methods
(getters & setters).
It Is a phenomenon of wrapping up data to provide security to the data with the help of access
specifier
just like an outer layer of a capsule provides security to the medicine that is present inside it

Access Specifiers in Python


Python provides three types of access specifiers to control the visibility of class members (variables
and methods). These are:

1. Public Access (No Underscore)


 Members declared as public can be accessed from anywhere in the program.
 There are no restrictions on accessing public attributes or methods.

2. Protected Access (_Single Underscore)


 Members declared as protected (with a single underscore _) should only be accessed
within the class and its subclasses.
 It is a convention, but still accessible outside the class (not strictly enforced).

3. Private Access (__Double Underscore)


 Members declared as private (__var) are not accessible outside the class.
 Python applies name mangling, which means private attributes get renamed internally (e.g.,
__var becomes _ClassName__var).

Difference Between Access Specifiers


Specifier Syntax Access Level
Public var_name Accessible anywhere (inside and outside the class)
Protected _var_name Accessible within the class and subclasses
Private __var_name Accessible only within the class (name mangling applies)
Encapsulation ensures controlled access to class attributes and prevents unintended modifications,
making the code more secure and maintainable. 🚨

60
Why Encapsulation?
🚨 Data Hiding: Prevents direct modification of object attributes.
🚨 Security: Protects important data from accidental changes.
🚨 Flexibility: Allows controlled access using methods.

Encapsulation in Python - Example


Python achieves encapsulation using private (__variable) and protected (_variable) attributes.

class BankAccount:
def __init__(self, balance):
self.__balance = balance # Private variable (Encapsulated)

def deposit(self, amount):


if amount > 0:
self.__balance += amount
print(f"Deposited: {amount}")
else:
print("Invalid deposit amount")

def withdraw(self, amount):


if 0 < amount <= self.__balance:
self.__balance -= amount
print(f"Withdrawn: {amount}")
else:
print("Insufficient balance or invalid amount")

def get_balance(self): # Getter method


return self.__balance

# Creating an account
acc = BankAccount(1000)
[Link](500)
[Link](300)
print("Balance:", acc.get_balance())

# Trying to access private variable directly


# print(acc.__balance) # ❌ AttributeError: 'BankAccount' object has no attribute '__balance'

✔ Private variable __balance cannot be accessed directly.


✔ Access is only through get_balance(), deposit(), and withdraw().

Encapsulation Levels in Python


Python does not have strict access control like Java or C++, but follows naming conventions:

Access Modifier Example Access


Public name Accessible everywhere
Protected _name Intended for subclass use (not enforced)

61
Access Modifier Example Access
Private __name Cannot be accessed directly from outside

Example of Protected and Private Variables


class Car:
def __init__(self, brand, speed):
[Link] = brand # Public variable
self._speed = speed # Protected variable
self.__engine = "V8" # Private variable

def show_details(self):
return f"Car: {[Link]}, Speed: {self._speed}, Engine: {self.__engine}"

car = Car("Tesla", 200)

print([Link]) # ✅ Public variable, accessible


print(car._speed) # ⚠️

Sub-Topic : Abstraction

Abstraction in Python
Abstraction is an Object-Oriented Programming (OOP) principle that hides implementation
details and exposes only the necessary functionalities. It helps in reducing code complexity by
focusing on what an object does rather than how it does it.

Key Features of Abstraction


✅ Hides unnecessary details and only shows relevant information.
✅ Reduces complexity by separating implementation from the user.
✅ Increases flexibility by allowing changes in implementation without affecting users.
✅ Implemented using abstract classes and methods in Python.

How is Abstraction Implemented in Python?


Python provides abstraction using the ABC (Abstract Base Class) module from the abc package.
1. Abstract Class
 An abstract class cannot be instantiated.
 It serves as a blueprint for other classes.
 Contains at least one abstract method (a method with no implementation).
2. Abstract Method
 A method that has no body and must be implemented by subclasses.

62
 Defined using the @abstractmethod decorator.

Example of Abstraction in Python

from abc import ABC, abstractmethod

# Abstract Class
class Vehicle(ABC):
@abstractmethod
def start(self): # Abstract Method
pass

# Concrete Class
class Car(Vehicle):
def start(self):
return "Car engine starts with a key."

class Bike(Vehicle):
def start(self):
return "Bike starts with a self-start button."

# Creating objects
car = Car()
bike = Bike()

print([Link]()) # Output: Car engine starts with a key.


print([Link]()) # Output: Bike starts with a self-start button.

Advantages of Abstraction
✔ Hides Complexity – Users don't need to know how methods work internally.
✔ Enhances Security – Prevents direct access to certain functionalities.
✔ Improves Code Reusability – Encourages the use of common base classes.

Real-World Example
Think of a TV remote – You press buttons to change the channel, but you don't need to know the
internal circuit workings. That's abstraction in action!

What is a Concrete Class in Python?


A concrete class is a fully implemented class in Python that can be instantiated (i.e., objects can be
created from it). Unlike an abstract class, a concrete class must provide implementations for all
its methods.

Key Features of a Concrete Class


✅ Can be instantiated – Objects can be created from it.
✅ Provides full method implementations – No abstract methods.

63
✅ Used in real-world applications – Implements logic for practical use.
✅ Can inherit from abstract classes – But must implement abstract methods.

Example of a Concrete Class

class Car: # Concrete Class


def start(self):
return "Car is starting..."

def stop(self):
return "Car is stopping..."

# Creating an object
my_car = Car()
print(my_car.start()) # Output: Car is starting...
print(my_car.stop()) # Output: Car is stopping...

✔ Here, Car is a concrete class because it has complete implementations for all methods.

Concrete Class vs. Abstract Class


Feature Concrete Class Abstract Class
Can be instantiated? ✅Yes ❌ No
✅Yes (must be overridden in a
Can have abstract methods? ❌ No
subclass)
Can have fully implemented
✅Yes ✅Yes (but not always)
methods?
Implements
Purpose Serves as a blueprint for other classes
functionality

Main Topic : Advanced Python

Sub-Topic: Lambda Function

Lambda Function in Python


A lambda function in Python is an anonymous (nameless) function that is defined
using the lambda keyword. It is a single-line function that can take multiple
arguments but only one expression.

Syntax of Lambda Function

64
lambda arguments: expression

 lambda – Keyword to define a lambda function.


 arguments – Input values (similar to function parameters).
 expression – The operation to be performed (returns the result).

Example: Basic Lambda Function

# Normal function
def add(a, b):
return a + b

# Lambda function equivalent


add_lambda = lambda a, b: a + b

print(add(5, 3)) # Output: 8


print(add_lambda(5, 3)) # Output: 8

✔ Both functions return the sum of two numbers.

Where is Lambda Function Used?


1. In Short Operations – When you need a simple function for a small task.
2. With map() Function – To apply a function to each element in a list.
3. With filter() Function – To filter elements based on a condition.
4. With sorted() Function – To sort based on custom logic.

Key Features of Lambda Functions


✅ Anonymous – No need to define with a function name.
✅ Concise – Written in a single line.
✅ Used in Functional Programming – Works well with map(), filter(), etc.
✅ Cannot Have Multiple Statements – Only one expression is allowed.

Sub-Topic : Map Function

65
map() Function in Python
The map() function in Python is used to apply a function to each item in an
iterable (like a list or tuple) and return a new iterable with the modified values.

Syntax of map()

map(function, iterable)

 function → A function to apply to each element.


 iterable → A sequence (list, tuple, etc.) whose elements will be processed.

Example 1: Using map() with a Regular Function

def square(num):
return num ** 2

numbers = [1, 2, 3, 4, 5]
result = map(square, numbers)

print(list(result)) # Output: [1, 4, 9, 16, 25]

✔ Each element in numbers is squared.


Advantages of map()
✅ Saves time – No need for explicit loops.
✅ Improves readability – Cleaner, functional programming style.
✅ Works with multiple iterables – Processes multiple sequences simultaneously.

Sub-Topic : Filter Function

filter() Function in Python


The filter() function is used to filter elements from an iterable (like a list or
tuple) based on a condition. It only keeps the elements for which the function
returns True.

66
Syntax of filter()

filter(function, iterable)

 function → A function that returns True or False.


 iterable → A sequence (list, tuple, etc.) to filter.

Example 1: Using filter() with a Regular Function

def is_even(num):
return num % 2 == 0

numbers = [1, 2, 3, 4, 5, 6]
result = filter(is_even, numbers)

print(list(result)) # Output: [2, 4, 6]

✔ Only even numbers are kept.

Sub-Topic : Comprehension

Advantages of Comprehensions
✅ More readable than loops.
✅ More concise than traditional loops.
✅ Faster execution due to optimized internal implementation.
✅ Memory efficient (especially generators).

in Python provides a concise way to create sequences (lists,


Comprehension

sets, dictionaries, etc.) using a single line of code instead of


using loops.

Types of Comprehensions in Python


1🚨 List Comprehension
2🚨 Dictionary Comprehension
3🚨 Set Comprehension
4️⃣🚨 Generator Comprehension
67
List Comprehension in Python
List comprehension is a concise way to create lists using a single line of code instead of a loop.

1🚨 Basic Syntax (Without if)


Syntax:

[expression for item in iterable]

Example: Create a list of squares

numbers = [1, 2, 3, 4, 5]
squares = [x ** 2 for x in numbers]
print(squares) # Output: [1, 4, 9, 16, 25]

✔ Each number is squared and added to the list.

2🚨 List Comprehension With if Condition


Syntax:

[expression for item in iterable if condition]

Example: Get even numbers from a list

numbers = [1, 2, 3, 4, 5, 6]
evens = [x for x in numbers if x % 2 == 0]
print(evens) # Output: [2, 4, 6]

✔ Only even numbers are included in the list.

3🚨 List Comprehension With if-else Condition


Syntax:

[expression_if_true if condition else expression_if_false for item in iterable]

Example: Label numbers as even or odd

numbers = [1, 2, 3, 4, 5]
labels = ["Even" if x % 2 == 0 else "Odd" for x in numbers]
print(labels) # Output: ['Odd', 'Even', 'Odd', 'Even', 'Odd']

68
✔ Assigns "Even" for even numbers and "Odd" for odd numbers.

Comparison Table
Type Syntax Example Output
Basic [x for x in iterable] [1, 4, 9, 16, 25]
With if [x for x in iterable if condition] [2, 4, 6]
[x if condition else y for x in ['Odd', 'Even', 'Odd',
With if-else
iterable] 'Even']

Tuple comprehension is not directly supported in Python.


Instead, when you use parentheses () instead of square brackets [], Python
creates a generator object instead of a tuple. This is known as

generator comprehension.

1🚨 Basic Tuple (Generator) Comprehension


Syntax:

(expression for item in iterable)

Example: Creating a generator for squares

numbers = [1, 2, 3, 4, 5]
squares = (x ** 2 for x in numbers)
print(squares) # Output: <generator object at 0x...>
print(tuple(squares)) # Output: (1, 4, 9, 16, 25)

✔ To get a tuple, convert it using tuple().

2🚨 Tuple Comprehension With if Condition


Syntax:

(expression for item in iterable if condition)

Example: Get even numbers as a generator and convert to a tuple

numbers = [1, 2, 3, 4, 5, 6]
evens = (x for x in numbers if x % 2 == 0)
print(tuple(evens)) # Output: (2, 4, 6)

69
✔ Only even numbers are included in the tuple.

3🚨 Tuple Comprehension With if-else Condition


Syntax:

(expression_if_true if condition else expression_if_false for item in iterable)

Example: Label numbers as even or odd

numbers = [1, 2, 3, 4, 5]
labels = ("Even" if x % 2 == 0 else "Odd" for x in numbers)
print(tuple(labels)) # Output: ('Odd', 'Even', 'Odd', 'Even', 'Odd')

✔ Assigns "Even" for even numbers and "Odd" for odd numbers.

Comparison Table
Type Syntax Example Output
Basic (x for x in iterable) (1, 4, 9, 16, 25)
With if (x for x in iterable if condition) (2, 4, 6)
(x if condition else y for x in ('Odd', 'Even', 'Odd',
With if-else
iterable) 'Even')

🚨 Easy Definition
 Tuple comprehension does not exist in Python.
 Using () creates a generator instead of a tuple.
 Convert the generator to a tuple using tuple().

Dictionary Comprehension in Python


Dictionary comprehension provides a concise way to create dictionaries using a single line of
code instead of loops.

1🚨 Basic Dictionary Comprehension


Syntax:

{key_expression: value_expression for item in iterable}

Example: Create a dictionary of squares

numbers = [1, 2, 3, 4]
squares_dict = {x: x**2 for x in numbers}
print(squares_dict) # Output: {1: 1, 2: 4, 3: 9, 4: 16}

70
✔ Each number is a key, and its square is the value.

2🚨 Dictionary Comprehension With if Condition


Syntax:

{key_expression: value_expression for item in iterable if condition}

Example: Filter dictionary values (keep only even numbers)

numbers = [1, 2, 3, 4, 5]
even_squares_dict = {x: x**2 for x in numbers if x % 2 == 0}
print(even_squares_dict) # Output: {2: 4, 4: 16}

✔ Only squares of even numbers are included.

3🚨 Dictionary Comprehension With if-else Condition


Syntax:

{key_expression: value_if_true if condition else value_if_false for item in iterable}

Example: Categorize numbers as even or odd

numbers = [1, 2, 3, 4, 5]
labels_dict = {x: "Even" if x % 2 == 0 else "Odd" for x in numbers}
print(labels_dict) # Output: {1: 'Odd', 2: 'Even', 3: 'Odd', 4: 'Even', 5: 'Odd'}

✔ Assigns "Even" or "Odd" based on the number.

Comparison Table
Type Syntax Example Output
{1: 1, 2: 4, 3: 9,
Basic {key: value for item in iterable}
4: 16}
With if {key: value for item in iterable if condition} {2: 4, 4: 16}
With if- {key: value_if_true if condition else {1: 'Odd', 2:
else value_if_false for item in iterable} 'Even', 3: 'Odd'}

🚨 Easy Definition
 Dictionary comprehension is used to create dictionaries quickly.
 It replaces traditional loops with a single line of code.
 Can include if for filtering and if-else for conditional values.

71

Sub-Topic : File Handling

File Handling in Python


File handling in Python allows us to create, read, write, and delete files. Python provides built-in
functions to handle different types of files, such as text files (.txt) and binary files (.jpg, .pdf).

Opening a File (open())


Python's open() function is used to open a file.

Syntax:

file = open("filename", "mode")

Modes in File Handling


Mode Description
"r" Read mode (default). Opens a file for reading. Error if the file does not exist.
"w" Write mode. Creates a new file or overwrites an existing file.
"a" Append mode. Adds data to the end of the file.
"x" Create mode. Creates a new file but raises an error if the file already exists.
"b" Binary mode. Used with r, w, a, x for binary files (e.g., "rb", "wb").
"t" Text mode (default). Used for text files (e.g., "rt", "wt").

1🚨 Reading a File ("r")


file = open("[Link]", "r") # Open file in read mode
content = [Link]() # Read entire content
print(content)
[Link]() # Always close the file

✔ Closes the file after reading to free system resources.

Read Methods
Method Description
read() Reads the entire file.
read(n) Reads the first n characters.
readline() Reads one line at a time.
readlines() Reads all lines as a list.

72
Example: Reading line by line

file = open("[Link]", "r")


for line in file:
print([Link]()) # Removes extra newline characters
[Link]()

2🚨 Writing to a File ("w")


file = open("[Link]", "w") # Open file in write mode
[Link]("Hello, Python!") # Write to the file
[Link]()

✔ Overwrites existing content or creates a new file if it doesn't exist.

3🚨 Appending to a File ("a")


file = open("[Link]", "a") # Open file in append mode
[Link]("\nAdding new content!") # Appends text
[Link]()

✔ Does not overwrite but adds content at the end.

4️⃣🚨 Using with Statement (Best Practice)


Using with open() automatically closes the file after execution.

with open("[Link]", "r") as file:


content = [Link]()
print(content) # No need to manually close the file

5️⃣🚨 Deleting a File ([Link]())


import os
[Link]("[Link]") # Deletes the file

✔ To avoid errors, check if the file exists before deleting:

if [Link]("[Link]"):
[Link]("[Link]")
else:
print("File does not exist")

73
Summary of File Handling
Operation Mode Description
Read "r" Opens file for reading. Error if the file does not exist.
Write "w" Creates a new file or overwrites existing content.
Append "a" Adds content at the end without deleting old data.
Create "x" Creates a new file but gives an error if the file exists.
Binary "b" Used for binary files like images and PDFs.
Would you like examples for handling binary files (.jpg, .pdf)? 🚨

File Handling for SQL in Python


Python allows you to interact with SQL databases using SQLite (sqlite3 module) or other
databases like MySQL and PostgreSQL using external libraries.

1🚨 Working with SQLite in Python


SQLite is a lightweight database that does not require a separate server. It stores the database in a
single .db file.

Common SQLite Functions/Methods


Function/Method Description
[Link]("[Link]") Creates or opens a SQLite database file.
[Link]("SQL Query") Executes an SQL command.
[Link]() Saves (commits) changes to the database.
[Link]() Fetches all results from a SELECT query.
[Link]() Fetches one result from a SELECT query.
[Link]("SQL Query", data) Inserts multiple records at once.
[Link]() Closes the cursor.
[Link]() Closes the database connection.

2🚨 Creating and Connecting to a Database


import sqlite3

# Create or connect to a database file


conn = [Link]("my_database.db")

# Create a cursor object


cursor = [Link]()

74
print("Database connected successfully!")

# Close the connection


[Link]()

✔ Creates a new .db file if it doesn't exist.

3🚨 Creating a Table
conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER
)
""")

[Link]() # Save changes


[Link]() # Close connection

✔ Creates a users table with id, name, and age columns.


✔ Ensures the table is created only if it doesn't already exist.

4️⃣🚨 Inserting Data into the Table


conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("INSERT INTO users (name, age) VALUES (?, ?)", ("Alice", 25))
[Link]()

print("Data inserted successfully!")


[Link]()

✔ Uses placeholders ? to prevent SQL injection.


✔ commit() saves the changes.

5️⃣🚨 Inserting Multiple Records (executemany)


data = [
("Bob", 30),
("Charlie", 22),
("David", 27)

75
]

conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("INSERT INTO users (name, age) VALUES (?, ?)", data)


[Link]()

print("Multiple records inserted!")


[Link]()

✔ Inserts multiple rows efficiently.

6🚨 Fetching Data from the Table


conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("SELECT * FROM users")


rows = [Link]() # Fetch all rows

for row in rows:


print(row) # Prints each row as a tuple

[Link]()

✔ Retrieves and prints all user records.

7️⃣🚨 Fetching Specific Data (fetchone)


conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("SELECT * FROM users WHERE name = ?", ("Alice",))


row = [Link]() # Fetch only one row

print(row)

[Link]()

✔ Returns the first matching row.

8🚨 Updating Data in a Table


conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("UPDATE users SET age = ? WHERE name = ?", (26, "Alice"))

76
[Link]()

print("Record updated successfully!")


[Link]()

✔ Updates Alice’s age to 26.

9️⃣🚨 Deleting Data from a Table


conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("DELETE FROM users WHERE name = ?", ("Charlie",))


[Link]()

print("Record deleted successfully!")


[Link]()

✔ Deletes the user with the name Charlie.

🚨 Deleting a Table
conn = [Link]("my_database.db")
cursor = [Link]()

[Link]("DROP TABLE IF EXISTS users") # Deletes the table if it exists


[Link]()

print("Table deleted!")
[Link]()

✔ Removes the entire table from the database.

🚨 Storing SQL Queries in a File (.sql)


We can store SQL queries in a file ([Link]) and execute them in Python.

Example: [Link] file

CREATE TABLE IF NOT EXISTS employees (


id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
salary INTEGER
);
INSERT INTO employees (name, salary) VALUES ('John Doe', 50000);
INSERT INTO employees (name, salary) VALUES ('Jane Smith', 60000);

77
Executing the SQL File in Python

conn = [Link]("my_database.db")
cursor = [Link]()

with open("[Link]", "r") as sql_file:


sql_script = sql_file.read() # Read SQL file
[Link](sql_script) # Execute multiple SQL commands

[Link]()
[Link]()

✔ Executes all queries in the SQL file.

Summary of File Handling with SQL


Operation Function/Method Description
Connects or creates a
Connect to DB [Link]("[Link]")
database.
Creates a table in the
Create Table [Link]("CREATE TABLE ...")
database.
Insert Data [Link]("INSERT INTO ...") Inserts a single row.
Insert Multiple [Link]("INSERT INTO ...", Inserts multiple rows at
Rows data) once.
Retrieves all rows from the
Fetch Data [Link]()
result.
Fetch One
[Link]() Fetches one row only.
Record
Updates records in the
Update Data [Link]("UPDATE table SET ...")
table.
[Link]("DELETE FROM table
Delete Data Deletes specific records.
WHERE ...")
[Link]("DROP TABLE IF
Delete Table Deletes a table if it exists.
EXISTS ...")
Runs multiple SQL queries
Execute SQL File [Link](sql_script)
from a file.
Close Closes the database
[Link]()
Connection connection.

🚨 Key Takeaways
✅ SQLite stores data in a single file (.db).
✅ Always use commit() after modifying the database.
✅ Use fetchall() for multiple rows and fetchone() for a single row.
✅ Use executemany() for inserting multiple records efficiently.
✅ Use executescript() to run an entire SQL file in Python.

78
Sub-Topic : Exception handling

Exception Handling in Python


Exception Handling in Python is a mechanism to handle runtime errors and prevent program
crashes. It uses try, except, else, and finally blocks.

1🚨 What is an Exception?
An exception is an error that occurs during execution, disrupting the program flow.
Example:

x = 5 / 0 # ZeroDivisionError: division by zero

✔ This causes a runtime error.

2🚨 Handling Exceptions with try-except


We use try-except to handle exceptions gracefully.

Basic Try-Except Example

try:
x = 5 / 0 # Risky code
except ZeroDivisionError:
print("Cannot divide by zero!")

✔ Prevents the program from crashing.

3🚨 Handling Multiple Exceptions


We can catch different exceptions separately.

try:
a = int(input("Enter a number: ")) # ValueError if input is not a number
b = 5 / a # ZeroDivisionError if a = 0
except ZeroDivisionError:
print("Cannot divide by zero!")
except ValueError:
print("Invalid input! Please enter a number.")

✔ Handles multiple errors separately.

79
4️⃣🚨 Catching Multiple Exceptions in One except Block
try:
a = int(input("Enter a number: "))
b = 10 / a
except (ZeroDivisionError, ValueError) as e:
print("Error:", e)

✔ Handles multiple exceptions in one block.

5️⃣🚨 Using else with try-except


The else block runs only if no exception occurs.

try:
num = int(input("Enter a number: "))
print("Valid input:", num)
except ValueError:
print("Invalid number!")
else:
print("No errors occurred!")

✔ Executes else if there are no exceptions.

6🚨 Using finally for Cleanup


The finally block always executes, regardless of whether an exception occurs.

try:
file = open("[Link]", "r")
data = [Link]()
except FileNotFoundError:
print("File not found!")
finally:
print("Closing file.")
[Link]() # Ensures the file is closed

✔ Used for cleanup tasks like closing files or releasing resources.

7️⃣🚨 Raising Exceptions Manually (raise)


We can raise exceptions using raise.

x = -5
if x < 0:

80
raise ValueError("Negative value not allowed!")

✔ Stops execution and throws an error message.

8🚨 Custom Exceptions (User-Defined Exceptions)


We can create our own exception classes.

class NegativeNumberError(Exception):
pass # Custom exception class

def check_positive(num):
if num < 0:
raise NegativeNumberError("Negative number not allowed!")
return num

try:
print(check_positive(-10))
except NegativeNumberError as e:
print("Error:", e)

✔ Creates custom exceptions for specific errors.

9️⃣🚨 Nested Try-Except Blocks


We can nest try-except blocks inside each other.

try:
try:
x = int(input("Enter a number: "))
y = 10 / x
except ZeroDivisionError:
print("Cannot divide by zero!")
except ValueError:
print("Invalid input!")

✔ Handles exceptions inside nested try blocks.

🚨 Summary of Exception Handling in Python


Keyword Description
try Contains code that may cause an exception.
except Catches and handles exceptions.
else Executes code if no exception occurs.
finally Runs code whether an exception occurs or not.
raise Raises an exception manually.

81
Keyword Description
pass Used to define custom exceptions without adding code.

🚨 Key Takeaways
✅ Use try-except to prevent program crashes.
✅ Use finally for cleanup actions like closing files.
✅ Use raise to trigger custom exceptions.
✅ Handle multiple exceptions separately or in a single except block.
✅ Use else when you need to run code only if no exceptions occur.

List of All Built-in Exceptions in Python


Python provides many built-in exceptions that help identify different types of errors in a program.
Below is a comprehensive table of all Python exceptions with their descriptions.

Exception Categories
Python exceptions are categorized into different classes:

1🚨 Arithmetic Errors
Exception Name Description
ZeroDivisionError Dividing by zero.
OverflowError Numeric calculation exceeds limit.
FloatingPointError Floating point error (rarely occurs).

2🚨 Lookup Errors (Accessing Non-Existing Elements)


Exception Name Description
IndexError Accessing an invalid index in a list or tuple.
KeyError Accessing a non-existent dictionary key.

3🚨 Type & Value Errors


Exception Name Description
TypeError Invalid operation on incompatible data types.
ValueError Function receives an argument of the correct type but an inappropriate value.

82
4️⃣🚨 Import Errors
Exception Name Description
ImportError Import statement fails.
ModuleNotFoundError The specified module is not found.

5️⃣🚨 File & OS Errors


Exception Name Description
FileNotFoundError Trying to open a non-existing file.
PermissionError No permission to access a file.
IsADirectoryError File operation requested on a directory.
NotADirectoryError Directory operation requested on a file.
OSError Generic OS-related error.

6🚨 Name & Attribute Errors


Exception Name Description
NameError Using a variable before declaring it.
UnboundLocalError Local variable referenced before assignment.
AttributeError Invalid attribute reference or assignment.

7️⃣🚨 Syntax Errors


Exception Name Description
SyntaxError Incorrect Python syntax.
IndentationError Incorrect indentation.
TabError Mixing tabs and spaces in indentation.

8🚨 Runtime Errors
Exception Name Description
RuntimeError Generic runtime error.
RecursionError Exceeding the maximum recursion depth.

9️⃣🚨 Iteration & Stop Errors


Exception Name Description
StopIteration Raised by next() when an iterator is exhausted.
StopAsyncIteration Raised when an asynchronous iterator is exhausted.

83
Sub-Topic : Iterator

What is an Iterator in Python?


An iterator in Python is an object that allows you to traverse through a sequence (like a list, tuple,
or dictionary) one element at a time. Iterators are implemented using two methods:

1. __iter__(): Returns the iterator object itself.


2. __next__(): Returns the next value in the sequence. When there are no more elements, it
raises a StopIteration exception.

Example of an Iterator:

class MyNumbers:
def __iter__(self):
[Link] = 1
return self

def __next__(self):
if [Link] > 5: # Stop after 5 iterations
raise StopIteration
val = [Link]
[Link] += 1
return val

# Creating an iterator object


my_iter = MyNumbers()
iterator = iter(my_iter)

# Iterating through the numbers


for num in iterator:
print(num)

Output:

1
2
3
4
5

Built-in Iterators
Python has built-in iterators like lists, tuples, and dictionaries that can be used with the iter() and
next() functions.

my_list = [10, 20, 30]


my_iter = iter(my_list)

84
print(next(my_iter)) # 10
print(next(my_iter)) # 20
print(next(my_iter)) # 30

Sub-Topic : Generator

What is a Generator in Python?


A generator in Python is a special type of iterator that is used to yield values lazily (one at a time)
instead of storing them in memory. Generators are more memory-efficient than regular iterators or
lists.

Unlike normal functions that use return, generators use the yield keyword to produce a sequence
of values lazily, allowing them to be paused and resumed.

How to Create a Generator?


A generator is defined like a normal function but uses yield instead of return.
Example 1: Simple Generator

def my_generator():
yield 1
yield 2
yield 3

gen = my_generator()

print(next(gen)) # Output: 1
print(next(gen)) # Output: 2
print(next(gen)) # Output: 3

If you call next(gen) again, it will raise a StopIteration exception.

Example 2: Generator with a Loop


Generators are useful when dealing with large sequences.

def countdown(n):
while n > 0:
yield n
n -= 1

for num in countdown(5):


print(num)

Output:

85
4
3
2
1

Key Differences Between Generators and Iterators


Feature Iterators Generators
Memory Memory-efficient (yields values one
Can be memory-intensive (stores all values)
Usage at a time)
Requires implementing __iter__() and
Creation Uses yield inside a function
__next__()
Persistence Values are stored in memory Values are generated on the fly
Complexity More code required More concise and readable

When to Use Generators?


✅When dealing with large datasets (e.g., reading big files line by line).
✅When you need a lazy evaluation approach (values generated on demand).
✅When memory efficiency is important.

Sub-Topic : Decorator

What is a Decorator in Python?


A decorator is a special type of function in Python that modifies the behavior of another function
without changing its code.
Think of a decorator as a wrapper that adds extra functionality to a function before or after it runs.

🚨 How to Create a Simple Decorator


Here’s a basic example of a decorator that logs function execution:

1🚨 Basic Decorator

def my_decorator(func):
def wrapper():
print("Function is about to run...")
func()
print("Function has finished running.")
return wrapper

86
@my_decorator
def say_hello():
print("Hello, World!")

say_hello()

📌 Output:

Function is about to run...


Hello, World!
Function has finished running.

🚨 How It Works
1. my_decorator takes a function (func) as input.
2. It wraps func() inside another function called wrapper().
3. wrapper() adds extra behavior before and after calling func().
4. Using @my_decorator, we apply this behavior to say_hello() without modifying its
original code.

87

You might also like