Python Notes
Python Notes
Notes
Beginner to Advanced
File & Exception Handling NumPy & Pandas APIs & Automation
2. Control Flow
2.1 Conditionals (if/elif/else)
2.2 Loops (for, while)
2.3 Break, Continue, Pass
4. Data Structures
4.1 Lists
4.2 Tuples
4.3 Dictionaries
4.4 Sets
5. Object-Oriented Programming
5.1 Classes & Objects
5.2 Inheritance
5.3 Polymorphism
5.4 Encapsulation
6. File Handling
6.1 Reading & Writing Files
6.2 CSV & JSON Files
7. Exception Handling
7.1 try/except/finally
7.2 Custom Exceptions
Python follows the principle: 'There should be one — and preferably only one — obvious way to do it.' It
supports multiple programming paradigms including procedural, object-oriented, and functional
programming.
Key Characteristics
Feature Description
■ Terminal
python --version # e.g. Python 3.11.4
python -m pip --version # check pip package manager
Variable Assignment
■ Variable Assignment
# Basic assignment
name = "Alice" # str
age = 30 # int
height = 5.7 # float
is_active = True # bool
# Multiple assignment
x = y = z = 0
# Tuple unpacking
a, b, c = 1, 2, 3
# Type checking
print(type(name)) # <class 'str'>
print(isinstance(age, int)) # True
Strings in Detail
■ String Operations
s = "Hello, Python!"
# Methods
print([Link]()) # 'HELLO, PYTHON!'
print([Link]()) # 'hello, python!'
print([Link]('Python','World')) # 'Hello, World!'
print([Link](',')) # ['Hello', ' Python!']
print([Link]()) # removes leading/trailing spaces
print(len(s)) # 14
# Multi-line strings
text = """Line 1
Line 2
Line 3"""
# String formatting
print("%-10s %5d" % ("item", 42)) # old style
print("{:>10} {:5d}".format("item", 42)) # new style
■ Common Mistake: Never use mutable objects (lists, dicts) as default argument values in functions.
■ Best Practice: Use f-strings for string formatting — they are the fastest and most readable option in Python
3.6+.
1.4 Operators
Category Operators Example
■ Operator Examples
# Arithmetic
print(17 // 5) # 3 (floor division)
print(17 % 5) # 2 (modulus)
print(2 ** 10) # 1024 (exponentiation)
# Logical operators
x = 5
print(x > 0 and x < 10) # True
print(x < 0 or x == 5) # True
print(not x == 5) # False
# Chained comparison (Pythonic!)
print(0 < x < 10) # True
Summary — Chapter 1
Concept Key Points
Data Types int, float, str, list, tuple, dict, set, bool, None
2.1 Conditionals
■ Definition: Conditional statements allow a program to choose different execution paths based on
Boolean expressions.
■ if / elif / else
score = 85
# Nested conditions
x, y = 5, 10
if x > 0:
if y > 0:
print("Both positive")
■ Common Mistake: Python does NOT have a switch/case statement in versions < 3.10. Use if/elif chains or
dicts for dispatch tables.
■ Note: Python 3.10+ introduced 'match' (structural pattern matching).
2.2 Loops
for Loop
■ Definition: Iterates over any iterable (list, tuple, string, range, dict, etc.).
■ for Loop Examples
# Iterating a list
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)
# Iterating dict
d = {'a': 1, 'b': 2}
for key, value in [Link]():
print(f"{key} -> {value}")
# Nested loops
for i in range(3):
for j in range(3):
print(f"({i},{j})", end=" ")
print()
while Loop
■ Definition: Repeats a block as long as a condition is True.
■ while Loop Examples
count = 0
while count < 5:
print(count)
count += 1
class MyClass:
pass # empty class definition
print(power(3)) # 9
print(power(3, 3)) # 27
3.2 Arguments
■ Types of Arguments
# Positional
def add(a, b):
return a + b
add(3, 4) # a=3, b=4
# Keyword
add(b=4, a=3) # same result
# With sorted()
students = [('Alice', 88), ('Bob', 95), ('Carol', 72)]
[Link](key=lambda s: s[1], reverse=True)
print(students) # [('Bob',95),('Alice',88),('Carol',72)]
■ Best Practice: Use lambda only for simple one-liners. For complex logic, define a regular function for
readability.
# __name__ guard
if __name__ == '__main__':
print("Running as main script")
# code here runs only when script is executed directly
PI = 3.14159
# [Link]
from myutils import celsius_to_fahrenheit, is_palindrome
print(celsius_to_fahrenheit(100)) # 212.0
print(is_palindrome("racecar")) # True
Full module import math When using multiple items from module
Specific name from math import sqrt When using one or few items
4.1 Lists
■ Definition: An ordered, mutable sequence. Allows duplicate elements. Elements can be of any type.
■ List Operations
# Creation
lst = [1, 2, 3, 4, 5]
mixed = [1, 'two', 3.0, True]
nested = [[1,2], [3,4]]
# Access
print(lst[0]) # 1
print(lst[-1]) # 5
print(lst[1:3]) # [2, 3]
# Modify
lst[0] = 10
[Link](6) # add to end
[Link](1, 99) # insert at index
[Link]([7, 8]) # merge another list
# Remove
[Link](99) # remove by value
popped = [Link]() # remove & return last
popped2 = [Link](0) # remove & return at index
del lst[0] # delete by index
# Other
print(len(lst))
[Link](2) # count occurrences
[Link]() # empty the list
copy = [Link]() # shallow copy
4.2 Tuples
■ Definition: An ordered, immutable sequence. Faster than lists. Used for fixed collections (coordinates,
RGB values, DB records).
■ Tuple Operations
t = (1, 2, 3)
single = (42,) # single-element tuple NEEDS trailing comma
empty = ()
# Unpacking
x, y, z = t
a, *rest = (1, 2, 3, 4, 5) # a=1, rest=[2,3,4,5]
4.3 Dictionaries
■ Definition: An unordered (Python 3.7+ maintains insertion order) mapping of unique keys to values.
Keys must be immutable (str, int, tuple).
■ Dictionary Operations
# Creation
d = {'name': 'Alice', 'age': 30, 'city': 'NY'}
d2 = dict(name='Bob', age=25)
# Access
print(d['name']) # Alice
print([Link]('salary', 0)) # 0 (default if missing)
# Modify
d['age'] = 31 # update
d['email'] = 'a@[Link]' # add new key
[Link]({'city': 'LA', 'country': 'US'})
# Remove
del d['city']
val = [Link]('age') # remove & return
[Link]() # remove last inserted (3.7+)
# Iteration
for key in d:
print(key, d[key])
for k, v in [Link]():
print(f"{k}: {v}")
keys = list([Link]())
values = list([Link]())
# Dict comprehension
squares = {x: x**2 for x in range(1, 6)}
# {1:1, 2:4, 3:9, 4:16, 5:25}
4.4 Sets
■ Definition: An unordered collection of unique, immutable elements. Ideal for membership tests and
removing duplicates.
■ Set Operations
s1 = {1, 2, 3, 4}
s2 = {3, 4, 5, 6}
# Set operations
print(s1 | s2) # Union: {1,2,3,4,5,6}
print(s1 & s2) # Intersection: {3,4}
print(s1 - s2) # Difference: {1,2}
print(s1 ^ s2) # Symmetric diff: {1,2,5,6}
# Methods
[Link](5)
[Link](5) # raises KeyError if not found
[Link](99) # no error if not found
# Constructor (initializer)
def __init__(self, name, age):
# Instance attributes
[Link] = name
[Link] = age
# Instance method
def bark(self):
return f"{[Link]} says: Woof!"
# Create instances
dog1 = Dog("Buddy", 3)
dog2 = Dog("Max", 5)
print([Link]) # Buddy
print([Link]()) # Buddy says: Woof!
print([Link]) # Canis familiaris
print(dog1) # Dog(Buddy, 3)
print([Link]) # Canis familiaris
@property
def radius(self):
return self._radius
@[Link]
def radius(self, value):
if value < 0:
raise ValueError("Radius cannot be negative")
self._radius = value
@property
def area(self):
import math
return [Link] * self._radius ** 2
c = Circle(5)
print([Link]) # 78.539...
[Link] = 10 # uses setter
5.2 Inheritance
■ Definition: Inheritance allows a class (child) to acquire attributes and methods of another class
(parent). Promotes code reuse.
■ Inheritance
class Animal:
def __init__(self, name, sound):
[Link] = name
[Link] = sound
def speak(self):
return f"{[Link]} says {[Link]}"
def __str__(self):
return f"{self.__class__.__name__}({[Link]})"
class Dog(Animal):
def __init__(self, name):
super().__init__(name, "Woof") # call parent __init__
class Cat(Animal):
def __init__(self, name):
super().__init__(name, "Meow")
def purr(self):
return f"{[Link]} purrs..."
# Multiple inheritance
class Labrador(Dog):
breed = "Labrador"
d = Dog("Rex")
print([Link]()) # Rex says Woof
print([Link]("ball")) # Rex fetches the ball!
c = Cat("Whiskers")
print([Link]()) # Whiskers says Meow
# Check inheritance
print(isinstance(d, Dog)) # True
print(isinstance(d, Animal)) # True
print(issubclass(Dog, Animal)) # True
class Rectangle(Shape):
def __init__(self, w, h):
self.w, self.h = w, h
def area(self):
return self.w * self.h
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
import math
return [Link] * self.r ** 2
@property
def balance(self):
return self.__balance
acc = BankAccount(1000)
[Link](500)
print([Link]) # 1500
# acc.__balance # AttributeError — protected!
# Append to file
with open('[Link]', 'a') as f:
[Link]("Line 5\n")
# Write CSV
data = [['Name','Age','City'],['Alice',30,'NY'],['Bob',25,'LA']]
with open('[Link]', 'w', newline='') as f:
writer = [Link](f)
[Link](data)
# Read CSV
with open('[Link]', 'r') as f:
reader = [Link](f)
for row in reader:
print(row['Name'], row['Age'])
# Write JSON
config = {'host':'localhost', 'port':5432, 'debug':True}
with open('[Link]', 'w') as f:
[Link](config, f, indent=4)
# Read JSON
with open('[Link]', 'r') as f:
loaded = [Link](f)
print(loaded['port']) # 5432
# JSON ↔ string
json_str = [Link](config, indent=2)
parsed = [Link](json_str)
# Multiple exceptions
try:
x = int(input("Enter a number: "))
result = 100 / x
except ValueError:
print("Not a valid integer")
except ZeroDivisionError:
print("Cannot divide by zero")
except Exception as e: # catch-all
print(f"Unexpected error: {e}")
else:
print(f"Result: {result}") # runs if no exception
finally:
print("This always runs") # cleanup code
# Common exceptions
# ValueError — wrong type/value
# TypeError — wrong type
# IndexError — list index out of range
# KeyError — dict key not found
# FileNotFoundError — file missing
# AttributeError — object has no attribute
# NameError — variable not defined
7.2 Custom Exceptions
■ Custom Exception Classes
class ValidationError(Exception):
"""Raised when input validation fails."""
def __init__(self, message, field=None):
super().__init__(message)
[Link] = field
class InsufficientFundsError(Exception):
def __init__(self, balance, amount):
[Link] = balance
[Link] = amount
super().__init__(
f"Cannot withdraw {amount}. Balance: {balance}"
)
try:
process_age(-5)
except ValidationError as e:
print(f"Validation failed on field '{[Link]}': {e}")
# re-raising exceptions
try:
risky_operation()
except Exception as e:
print(f"Logging: {e}")
raise # re-raise the same exception
Chapter 8: Libraries — NumPy &
Pandas
8.1 NumPy
■ Definition: NumPy (Numerical Python) is the foundation for numerical computing in Python. It
provides the ndarray — an efficient N-dimensional array object.
■ NumPy Basics
import numpy as np
# Creating arrays
a = [Link]([1, 2, 3, 4, 5])
b = [Link]((3, 3)) # 3x3 zeros
c = [Link]((2, 4)) # 2x4 ones
d = [Link](0, 10, 2) # [0 2 4 6 8]
e = [Link](0, 1, 5) # [0. 0.25 0.5 0.75 1.]
r = [Link](3, 3) # 3x3 random [0,1)
# Operations (element-wise)
a = [Link]([1,2,3])
b = [Link]([4,5,6])
print(a + b) # [5 7 9]
print(a * b) # [4 10 18]
print(a ** 2) # [1 4 9]
print([Link](a)) # [1. 1.41 1.73]
# Matrix multiplication
A = [Link]([[1,2],[3,4]])
B = [Link]([[5,6],[7,8]])
print(A @ B) # [[19 22] [43 50]]
print([Link](A, B)) # same
# Statistical functions
data = [Link]([4,7,13,2,1])
print([Link](data)) # 5.4
print([Link](data)) # 4.03
print([Link](data)) # 1
print([Link](data)) # 13
print([Link](data)) # 27
# Reshaping
a = [Link](12)
b = [Link]((3, 4)) # 3 rows, 4 cols
c = [Link]() # back to 1D
8.2 Pandas
■ Definition: Pandas is the primary data analysis library for Python. Key structures: Series (1D) and
DataFrame (2D table).
■ Pandas Basics
import pandas as pd
# Creating a DataFrame
data = {
'Name': ['Alice','Bob','Carol','Dave'],
'Age': [25, 30, 35, 28],
'Salary': [50000, 65000, 80000, 55000],
'Dept': ['HR','IT','IT','Finance']
}
df = [Link](data)
# Basic inspection
print([Link](2)) # first 2 rows
print([Link](2)) # last 2 rows
print([Link]) # (4, 4)
print([Link]) # column types
print([Link]()) # statistics
print([Link]()) # memory, nulls
# Selecting data
print(df['Name']) # Series
print(df[['Name','Age']]) # DataFrame
print([Link][0]) # row by index
print([Link][0:2, 1:3]) # rows 0-1, cols 1-2
print([Link][0, 'Name']) # row label, col name
# Filtering
print(df[df['Age'] > 28])
print(df[df['Dept'] == 'IT'])
print(df[(df['Age'] > 25) & (df['Salary'] > 60000)])
# Adding columns
df['Tax'] = df['Salary'] * 0.2
df['Senior'] = df['Age'] >= 30
# GroupBy
grouped = [Link]('Dept')['Salary'].mean()
print(grouped)
# Sorting
df.sort_values('Salary', ascending=False, inplace=True)
# Reading/Writing
df.to_csv('[Link]', index=False)
df_loaded = pd.read_csv('[Link]')
df.to_excel('[Link]', index=False)
Chapter 9: APIs & Basic Automation
# GET request
response = [Link]('[Link]
print(response.status_code) # 200
print([Link]()) # parsed JSON dict
print([Link]['Content-Type'])
# POST request
payload = {'username': 'alice', 'password': 'secret'}
r = [Link]('[Link] json=payload)
# Error handling
try:
r = [Link]('[Link] timeout=5)
r.raise_for_status() # raises for 4xx/5xx
except [Link]:
print("Request timed out")
except [Link] as e:
print(f"HTTP error: {e}")
# Create directories
Path('new_folder/sub').mkdir(parents=True, exist_ok=True)
# List files
for f in Path('.').glob('*.py'):
print(f)
# File info
f = Path('[Link]')
print([Link]())
print([Link]().st_size) # size in bytes
# Copy/move
[Link]('[Link]', '[Link]')
[Link]('old_name.txt', 'new_name.txt')
# Rename
Path('[Link]').rename('[Link]')
# Delete
Path('[Link]').unlink() # delete file
[Link]('folder') # delete directory
# Environment variables
import os
db_url = [Link]('DATABASE_URL', 'localhost')
Chapter 10: Advanced Topics
10.1 Comprehensions
■ List, Dict, Set Comprehensions
# List comprehension
squares = [x**2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# With condition
evens = [x for x in range(20) if x % 2 == 0]
# Nested comprehension
matrix = [[i*j for j in range(1,4)] for i in range(1,4)]
# [[1,2,3],[2,4,6],[3,6,9]]
# Dict comprehension
word_len = {w: len(w) for w in ['hello','world','python']}
# {'hello':5, 'world':5, 'python':6}
# Set comprehension
unique_lengths = {len(w) for w in ['hello','hi','world']}
# {5, 2}
10.2 Generators
■ Generator Functions
# Generator with yield
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for _ in range(10):
print(next(fib), end=' ')
# 0 1 1 2 3 5 8 13 21 34
# Finite generator
def countdown(n):
while n > 0:
yield n
n -= 1
for val in countdown(5):
print(val) # 5 4 3 2 1
list(chain([1,2],[3,4],[5])) # [1,2,3,4,5]
10.3 Decorators
■ Definition: A decorator is a higher-order function that wraps another function to modify or extend its
behaviour.
■ Decorators
import time
from functools import wraps
# Basic decorator
def timer(func):
@wraps(func) # preserves original function metadata
def wrapper(*args, **kwargs):
start = [Link]()
result = func(*args, **kwargs)
end = [Link]()
print(f"{func.__name__} took {end-start:.4f}s")
return result
return wrapper
@timer
def slow_function(n):
[Link](n)
return "Done"
@repeat(3)
def greet(name):
print(f"Hello {name}")
# Built-in decorators
class MyClass:
count = 0
@classmethod
def get_count(cls):
return [Link]
@staticmethod
def validate(x):
return isinstance(x, int)
with Timer() as t:
sum(range(1000000))
# Using contextlib
from contextlib import contextmanager
@contextmanager
def managed_resource(name):
print(f"Opening {name}")
try:
yield name
finally:
print(f"Closing {name}")
with managed_resource("database") as r:
print(f"Using {r}")
Chapter 11: Practice Questions
Beginner Level
Q1. Write a program that takes a number and prints whether it is even or odd.
Answer: n = int(input()); print('Even' if n%2==0 else 'Odd')
Q2. Write a function that returns the factorial of a number using recursion.
Answer: def fact(n): return 1 if n<=1 else n*fact(n-1)
Intermediate Level
Q6. Implement a stack class using a Python list with push, pop, peek, and is_empty methods.
Answer: class Stack: def __init__(self): [Link]=[] def push(self,x): [Link](x) def pop(self):
return [Link]() def peek(self): return [Link][-1] def is_empty(self): return len([Link])==0
Q7. Write a decorator that caches the results of function calls (memoization).
Answer: Use functools.lru_cache or implement a dict-based cache inside a closure.
Q9. Parse a CSV file and compute the average of a numeric column.
Answer: Use [Link] and compute mean of the column values.
Advanced Level
Q11. Implement a thread-safe singleton class in Python.
Answer: Use [Link] and double-checked locking in __new__ or __init__.
Q13. Use Pandas to: load a CSV, group by a category column, compute multiple aggregations, and
export the result.
Answer: [Link]('col').agg({'num':'mean','amt':'sum'}).reset_index().to_csv(...)
Q14. Write an async function that makes 3 API calls concurrently using asyncio.
Answer: Use [Link]() with [Link] for concurrent calls.
String Formatting
Style Syntax Example