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

Python Complete Notes

This document serves as a comprehensive reference for Python programming, covering topics from basic concepts to intermediate-level features, including data types, control flow, functions, and object-oriented programming. It includes practical examples, interview questions, and explanations of key Python features and applications. The content is structured in a way that is suitable for interview preparation, job readiness, and academic studies.

Uploaded by

thanvitha02.d
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 views31 pages

Python Complete Notes

This document serves as a comprehensive reference for Python programming, covering topics from basic concepts to intermediate-level features, including data types, control flow, functions, and object-oriented programming. It includes practical examples, interview questions, and explanations of key Python features and applications. The content is structured in a way that is suitable for interview preparation, job readiness, and academic studies.

Uploaded by

thanvitha02.d
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

PYTHON

Complete Reference Notes


For Interview Preparation · Job Readiness · Academic Studies
Beginner to Intermediate — All Concepts Explained with Examples

Table of Contents
Chapter 1 — Introduction to Python
Chapter 2 — Variables, Data Types & Operators
Chapter 3 — Control Flow — if/elif/else, loops
Chapter 4 — Functions
Chapter 5 — Strings
Chapter 6 — Lists
Chapter 7 — Tuples
Chapter 8 — Dictionaries
Chapter 9 — Sets
Chapter 10 — File Handling
Chapter 11 — Modules & Packages
Chapter 12 — Object-Oriented Programming
Chapter 13 — Exception Handling
Chapter 14 — NumPy Basics
Chapter 15 — Comprehensions & Lambda
Chapter 16 — Interview Q&A; Quick Reference
Chapter 1 — Introduction to Python

What is Python?
Python is a high-level, interpreted, general-purpose programming language created by Guido van Rossum in
1991. It emphasizes code readability and simplicity. Python supports multiple programming paradigms:
procedural, object-oriented, and functional programming.

Key Features
• Easy to Learn: Simple English-like syntax.
• Interpreted: Executes line by line — no compilation needed.
• Dynamically Typed: No need to declare variable types.
• Cross-Platform: Runs on Windows, Linux, macOS.
• Huge Standard Library: Built-in modules for almost everything.
• Open Source & Free: Freely available.
• Object-Oriented: Supports classes and objects.

Python Applications
• Web Development (Django, Flask)
• Data Science & Machine Learning (NumPy, Pandas, TensorFlow)
• Automation & Scripting
• Artificial Intelligence
• Game Development (Pygame)
• Desktop Applications
• IoT & Embedded Systems

First Python Program


# Your first Python program
print("Hello, World!")

# Input from user


name = input("Enter your name: ")
print("Hello,", name)

# Output:
# Hello, World!
# Enter your name: Ravi
# Hello, Ravi

Interview: Q: Why is Python called interpreted? A: Python executes code line-by-line through an interpreter at
runtime, unlike C/C++ which compile the entire code first.

Interview: Q: What is PEP 8? A: PEP 8 is Python's official style guide — it defines coding conventions like
using 4 spaces for indentation, snake_case for variables, etc.
Chapter 2 — Variables, Data Types & Operators

Variables
A variable is a name that refers to a value stored in memory. In Python, variables are created when you assign
a value — no declaration needed.
name = "Priya" # str
age = 21 # int
gpa = 8.5 # float
is_student = True # bool

# Multiple assignment
x = y = z = 0
a, b, c = 1, 2, 3

# Type checking
print(type(name)) # <class 'str'>
print(type(age)) # <class 'int'>

# Variable naming rules:


# ✓ start with letter or _
# ✓ can contain letters, digits, _
# ✗ cannot start with digit
# ✗ cannot be a keyword (if, for, while...)

Data Types
Python has the following built-in data types:
# Numeric
x = 10 # int
y = 3.14 # float
z = 2 + 3j # complex

# Text
s = "Hello" # str

# Boolean
flag = True # bool (True / False)

# None type
val = None # NoneType

# Collections
lst = [1, 2, 3] # list — mutable, ordered
tup = (1, 2, 3) # tuple — immutable, ordered
dct = {"a": 1, "b": 2} # dict — key-value pairs
st = {1, 2, 3} # set — unordered, unique

# Type conversion
print(int("42")) # 42
print(float(10)) # 10.0
print(str(3.14)) # '3.14'
print(bool(0)) # False
print(bool(1)) # True

Operators
Arithmetic Operators
a, b = 15, 4
print(a + b) # 19 Addition
print(a - b) # 11 Subtraction
print(a * b) # 60 Multiplication
print(a / b) # 3.75 Division (always float)
print(a // b) # 3 Floor Division (integer result)
print(a % b) # 3 Modulus (remainder)
print(a ** b) # 50625 Exponentiation (15^4)

Comparison & Logical Operators


# Comparison (returns True/False)
print(5 > 3) # True
print(5 == 5) # True
print(5 != 3) # True
print(5 >= 5) # True

# Logical
print(True and False) # False
print(True or False) # True
print(not True) # False

# Identity
x = [1, 2]
y = x
print(x is y) # True (same object)
print(x is [1,2]) # False (different object)

# Membership
lst = [1, 2, 3, 4]
print(3 in lst) # True
print(5 not in lst) # True

Interview: Q: What is the difference between == and is? == compares values; is compares object identity
(memory address). Two lists with same values: == is True, is is False.
Chapter 3 — Control Flow

if / elif / else
Python uses indentation (4 spaces) instead of curly braces to define blocks.
marks = int(input("Enter marks: "))

if marks >= 90:


print("Grade: S")
elif marks >= 80:
print("Grade: A")
elif marks >= 70:
print("Grade: B")
elif marks >= 60:
print("Grade: C")
elif marks >= 40:
print("Grade: D — Pass")
else:
print("Grade: F — Fail")

# Ternary (one-line if-else)


result = "Pass" if marks >= 40 else "Fail"
print(result)

for Loop
Used to iterate over a sequence (list, tuple, string, range).
# Basic for loop
for i in range(5):
print(i, end=" ") # 0 1 2 3 4

# range(start, stop, step)


for i in range(1, 11, 2):
print(i, end=" ") # 1 3 5 7 9

# Iterate over list


fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)

# Enumerate — get index and value


for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")

# Nested loop — multiplication table


for i in range(1, 4):
for j in range(1, 4):
print(f"{i}x{j}={i*j}", end=" ")
print()

while Loop
n = 1
while n <= 5:
print(n, end=" ")
n += 1
# Output: 1 2 3 4 5

# while with break and continue


i = 0
while i < 10:
i += 1
if i == 3:
continue # skip 3
if i == 7:
break # stop at 7
print(i, end=" ")
# Output: 1 2 4 5 6

# while-else
count = 0
while count < 3:
print(count)
count += 1
else:
print("Loop ended normally")

Tip: Use for loops when you know the number of iterations. Use while loops when the stop condition is dynamic.

Interview: Q: What is the difference between break and continue? break exits the loop entirely; continue skips
the current iteration and moves to the next.
Chapter 4 — Functions
A function is a reusable block of code that performs a specific task. Functions improve modularity and reduce
code repetition.

Defining and Calling Functions


# Basic function
def greet():
print("Hello, World!")

greet() # call

# Function with parameters


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

greet_user("Ravi")

# Function with return value


def add(a, b):
return a + b

result = add(5, 3)
print(result) # 8

# Multiple return values


def min_max(lst):
return min(lst), max(lst)

lo, hi = min_max([3, 1, 7, 2, 9])


print(lo, hi) # 1 9

Default, Keyword & Variable Arguments


# Default arguments
def power(base, exp=2):
return base ** exp

print(power(3)) # 9 (uses default exp=2)


print(power(3, 3)) # 27

# Keyword arguments
def student_info(name, age, branch):
print(f"{name}, {age}, {branch}")

student_info(age=20, branch="CSE", name="Priya")

# *args — variable positional arguments


def total(*nums):
return sum(nums)

print(total(1, 2, 3, 4)) # 10

# **kwargs — variable keyword arguments


def display(**info):
for k, v in [Link]():
print(f" {k}: {v}")

display(name="Ravi", city="Mangaluru", gpa=8.9)


Scope — LEGB Rule
x = "Global"

def outer():
x = "Enclosing"
def inner():
x = "Local"
print("Inner:", x) # Local
inner()
print("Outer:", x) # Enclosing

outer()
print("Global:", x) # Global

# global keyword
count = 0
def increment():
global count
count += 1

increment()
print(count) # 1

Recursive Functions
# Factorial using recursion
def factorial(n):
if n == 0 or n == 1: # base case
return 1
return n * factorial(n - 1) # recursive call

print(factorial(5)) # 120

# Fibonacci
def fib(n):
if n <= 1:
return n
return fib(n-1) + fib(n-2)

print([fib(i) for i in range(8)]) # [0,1,1,2,3,5,8,13]

Interview: Q: What is recursion? A function that calls itself. Every recursive function needs a base case to stop,
otherwise it causes infinite recursion (RecursionError).
Interview: Q: What are *args and **kwargs? *args collects extra positional arguments as a tuple; **kwargs
collects extra keyword arguments as a dictionary.
Chapter 5 — Strings
A string is a sequence of characters enclosed in single (''), double (""), or triple (''' ''') quotes. Strings are
immutable in Python.

String Operations
s = "Hello, Python!"

# Length
print(len(s)) # 14

# Indexing (0-based, negative from end)


print(s[0]) # H
print(s[-1]) # !

# Slicing [start:stop:step]
print(s[0:5]) # Hello
print(s[7:]) # Python!
print(s[:5]) # Hello
print(s[::-1]) # !nohtyP ,olleH (reversed)

# Concatenation & Repetition


print("Hi" + " " + "there") # Hi there
print("Ha" * 3) # HaHaHa

# Membership
print("Python" in s) # True

String Methods
s = " Hello, World! "

print([Link]()) # "Hello, World!" — remove spaces


print([Link]()) # " hello, world! "
print([Link]()) # " HELLO, WORLD! "
print([Link]()) # " Hello, World! "
print([Link]("World", "Python")) # " Hello, Python! "

words = "apple,banana,cherry"
print([Link](",")) # ['apple', 'banana', 'cherry']
print(",".join(["a","b","c"])) # a,b,c

s2 = "Python Programming"
print([Link]("gram")) # 12 (index of first occurrence)
print([Link]("m")) # 2
print([Link]("Py")) # True
print([Link]("ing")) # True

# Check type
print("abc123".isalnum()) # True
print("hello".isalpha()) # True
print("123".isdigit()) # True
print(" ".isspace()) # True

String Formatting
name = "Ravi"
age = 21
gpa = 8.567

# f-strings (recommended, Python 3.6+)


print(f"Name: {name}, Age: {age}, GPA: {gpa:.2f}")

# format() method
print("Name: {}, Age: {}".format(name, age))

# % formatting (old style)


print("Name: %s, Age: %d" % (name, age))

# Output:
# Name: Ravi, Age: 21, GPA: 8.57

Interview: Q: Are strings mutable in Python? No. Strings are immutable — you cannot change individual
characters. Any operation creates a new string.

Interview: Q: What is the difference between find() and index()? Both find a substring. find() returns -1 if not
found; index() raises ValueError if not found.
Chapter 6 — Lists
A list is an ordered, mutable collection. Elements can be of any data type. Lists use square brackets [].

Creating & Accessing Lists


# Creating
nums = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
nested = [[1, 2], [3, 4], [5, 6]]
empty = []

# Accessing
print(nums[0]) # 1
print(nums[-1]) # 5
print(nums[1:4]) # [2, 3, 4]
print(nested[1][0]) # 3 (row 1, col 0)

# Length
print(len(nums)) # 5

List Methods
lst = [3, 1, 4, 1, 5, 9, 2, 6]

[Link](7) # add to end: [3,1,4,1,5,9,2,6,7]


[Link](0, 99) # insert at index: [99,3,1,4,1,5,9,2,6,7]
[Link](1) # remove first 1: [99,3,4,1,5,9,2,6,7]
popped = [Link]() # remove & return last: 7
popped2 = [Link](0) # remove & return at index 0: 99

[Link]() # sort ascending in-place


print(lst) # [1, 2, 3, 4, 5, 6, 9]

[Link](reverse=True) # sort descending


[Link]() # reverse in-place

print([Link](3)) # count occurrences of 3


print([Link](5)) # index of first 5

lst2 = [10, 20]


[Link](lst2) # add all elements of lst2

[Link]() # empty the list


copy_lst = [Link]() # shallow copy

List Operations & Iteration


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

# Membership
print(30 in nums) # True

# Iteration
for n in nums:
print(n, end=" ")

# enumerate
for i, val in enumerate(nums):
print(f"[{i}]={val}", end=" ")

# List comprehension
squares = [x**2 for x in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]

evens = [x for x in range(1, 11) if x % 2 == 0]


print(evens) # [2, 4, 6, 8, 10]

# sorted() — returns new sorted list (original unchanged)


orig = [5, 2, 8, 1]
s = sorted(orig)
print(orig) # [5, 2, 8, 1] unchanged
print(s) # [1, 2, 5, 8]

Interview: Q: Difference between append() and extend()? append() adds one element; extend() adds all
elements of an iterable to the list.

Interview: Q: Difference between sort() and sorted()? sort() modifies the list in place, returns None. sorted()
returns a new sorted list, original unchanged.
Chapter 7 — Tuples
A tuple is an ordered, immutable collection. Once created, elements cannot be added, removed, or changed.
Tuples use parentheses ().

Creating & Using Tuples


# Creating
t1 = (1, 2, 3)
t2 = (1,) # single element — comma required!
t3 = 1, 2, 3 # without parentheses (packing)
empty = ()

# Accessing
print(t1[0]) # 1
print(t1[-1]) # 3
print(t1[1:]) # (2, 3)

# Unpacking
a, b, c = t1
print(a, b, c) # 1 2 3

# Extended unpacking
first, *rest = (1, 2, 3, 4, 5)
print(first) # 1
print(rest) # [2, 3, 4, 5]

# Tuple methods
t = (3, 1, 4, 1, 5, 9, 2, 6, 1)
print([Link](1)) # 3
print([Link](5)) # 4

# Convert
lst = list(t) # tuple to list
tup = tuple(lst) # list to tuple

Why Use Tuples?


• Faster than lists (slightly better performance).
• Can be used as dictionary keys (lists cannot).
• Protect data from accidental modification.
• Used to return multiple values from functions.
# Tuple as dictionary key
locations = {(12.9716, 77.5946): "Bangalore",
(12.8698, 74.8431): "Mangaluru"}
print(locations[(12.9716, 77.5946)]) # Bangalore

# Return multiple values


def circle(r):
import math
return [Link] * r**2, 2 * [Link] * r

area, perimeter = circle(5)


print(f"Area: {area:.2f}, Perimeter: {perimeter:.2f}")

Interview: Q: Can a tuple contain mutable objects? Yes. A tuple is immutable (you cannot reassign its
references) but if it contains a list, that list itself can be modified.
Chapter 8 — Dictionaries
A dictionary stores data as key-value pairs. Keys must be unique and immutable. Dictionaries are mutable and
maintain insertion order (Python 3.7+).

Creating & Accessing Dictionaries


# Creating
student = {"name": "Ravi", "age": 21, "gpa": 8.5}
empty = {}
d = dict(name="Priya", age=20)

# Accessing
print(student["name"]) # Ravi
print([Link]("age")) # 21
print([Link]("city", "N/A")) # N/A (default if missing)

# Modifying
student["age"] = 22 # update
student["branch"] = "CSE" # add new key

# Deleting
del student["gpa"]
popped = [Link]("age") # remove & return
[Link]() # remove last inserted item

Dictionary Methods
d = {"a": 1, "b": 2, "c": 3}

print(list([Link]())) # ['a', 'b', 'c']


print(list([Link]())) # [1, 2, 3]
print(list([Link]())) # [('a',1), ('b',2), ('c',3)]

# Iteration
for key, val in [Link]():
print(f" {key} => {val}")

# update — merge dictionaries


[Link]({"d": 4, "e": 5})

# in operator — checks keys


print("a" in d) # True
print(5 in d) # False (checks keys, not values)

# setdefault — add key only if not present


[Link]("f", 0)

# Dictionary comprehension
squares = {x: x**2 for x in range(1, 6)}
print(squares) # {1:1, 2:4, 3:9, 4:16, 5:25}

Interview: Q: Can a list be a dictionary key? No. Dictionary keys must be hashable (immutable). Lists are
mutable and unhashable. Use tuples instead.
Chapter 9 — Sets
A set is an unordered collection of unique elements. Useful for removing duplicates and membership testing.
Sets are mutable; frozensets are immutable.
# Creating
s = {1, 2, 3, 4, 5}
s2 = set([1, 2, 2, 3, 3]) # {1, 2, 3} — duplicates removed
empty = set() # NOT {} — that's an empty dict

# Adding / Removing
[Link](6)
[Link](10) # no error if missing
[Link](1) # KeyError if missing

# Set Operations
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 diff: {1,2,5,6}

# Subset / Superset
print({1,2}.issubset(a)) # True
print([Link]({1,2})) # True

# Remove duplicates from list using set


lst = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(lst))
print(unique) # [1, 2, 3, 4] (order not guaranteed)

Interview: Q: When would you use a set over a list? When you need uniqueness, fast membership testing (O(1)
vs O(n) for lists), or set operations like union/intersection.
Chapter 10 — File Handling
File handling allows reading from and writing to files. Python's built-in open() function is used with different
modes.

File Modes
# Mode Description
# 'r' Read (default) — error if file not found
# 'w' Write — creates file, overwrites if exists
# 'a' Append — adds to end without overwriting
# 'x' Create — error if file exists
# 'rb' Read binary
# 'wb' Write binary
# 'r+' Read and write

Reading Files
# Method 1: read() — reads entire file
with open("[Link]", "r") as f:
content = [Link]()
print(content)

# Method 2: readline() — reads one line at a time


with open("[Link]", "r") as f:
line = [Link]()
while line:
print([Link]())
line = [Link]()

# Method 3: readlines() — returns list of lines


with open("[Link]", "r") as f:
lines = [Link]()
print(lines) # ['line1\n', 'line2\n', ...]

# Method 4: Iterate directly (most Pythonic)


with open("[Link]", "r") as f:
for line in f:
print([Link]())

Writing Files
# Writing
with open("[Link]", "w") as f:
[Link]("Line 1\n")
[Link]("Line 2\n")

# Writing multiple lines


lines = ["apple\n", "banana\n", "cherry\n"]
with open("[Link]", "w") as f:
[Link](lines)

# Appending
with open("[Link]", "a") as f:
[Link]("Line 3 (appended)\n")

Binary Files
# Writing binary
data = bytes([72, 101, 108, 108, 111]) # "Hello" in ASCII
with open("[Link]", "wb") as f:
[Link](data)
# Reading binary
with open("[Link]", "rb") as f:
content = [Link]()
print(content) # b'Hello'
print([Link]()) # Hello

Tip: Always use the 'with' statement for file operations. It automatically closes the file even if an exception
occurs.

Interview: Q: What is the difference between read() and readlines()? read() returns the entire content as a
single string. readlines() returns a list of lines.
Chapter 11 — Modules & Packages
A module is a Python file containing functions, classes, and variables that can be reused. A package is a
directory of modules.

Importing Modules
# Variant 1: import module
import math
print([Link](16)) # 4.0
print([Link]) # 3.14159...
print([Link](4.7)) # 4

# Variant 2: from module import specific


from math import sqrt, pi
print(sqrt(25)) # 5.0
print(pi) # 3.14159...

# Variant 3: import all


from math import *
print(ceil(4.2)) # 5

# Alias
import numpy as np
import pandas as pd

Built-in Modules
import random
import time
import os
import sys

# random module
print([Link](1, 10)) # random int 1-10
print([Link]()) # random float 0.0-1.0
print([Link]([1,2,3,4,5])) # random element
lst = [1,2,3,4,5]
[Link](lst) # shuffle in-place

# time module
print([Link]()) # current timestamp (seconds)
print([Link]()) # human-readable time
[Link](1) # pause 1 second

# os module
print([Link]()) # current directory
print([Link]('.')) # list files
[Link]("myfolder", exist_ok=True)
print([Link]("[Link]")) # check if file exists

# math module
import math
print([Link](5)) # 120
print([Link](12, 8)) # 4
print([Link](100, 10)) # 2.0

Creating Your Own Module


# File: [Link]
def add(a, b):
return a + b
def subtract(a, b):
return a - b

def factorial(n):
if n <= 1:
return 1
return n * factorial(n-1)

PI = 3.14159

# File: [Link]
import mymath
print([Link](5, 3)) # 8
print([Link]) # 3.14159
print([Link](5)) # 120
Chapter 12 — Object-Oriented Programming (OOP)
OOP is a programming paradigm that organizes code into objects. Python fully supports OOP with the four
pillars: Encapsulation, Inheritance, Polymorphism, and Abstraction.

Classes & Objects


class Student:
college = "VTU" # class attribute (shared)

def __init__(self, name, age, marks): # constructor


[Link] = name # instance attributes
[Link] = age
[Link] = marks

def greet(self):
print(f"Hi, I'm {[Link]} from {[Link]}")

def grade(self):
if [Link] >= 90: return 'S'
elif [Link] >= 80: return 'A'
elif [Link] >= 70: return 'B'
else: return 'C'

def __str__(self): # string representation


return f"Student({[Link]}, {[Link]})"

def __repr__(self): # official representation


return f"Student(name={[Link]!r}, age={[Link]!r})"

# Creating objects
s1 = Student("Ravi", 20, 85)
s2 = Student("Priya", 21, 92)

[Link]() # Hi, I'm Ravi from VTU


print([Link]()) # A
print(s2) # Student(Priya, 21)
print([Link]) # VTU (class attribute)

Inheritance
Inheritance allows a class (child) to acquire properties and methods of another class (parent). It promotes code
reuse.
class Animal:
def __init__(self, name):
[Link] = name

def eat(self):
print(f"{[Link]} eats food")

def speak(self):
print(f"{[Link]} makes a sound")

class Dog(Animal): # Dog inherits from Animal


def speak(self): # override
print(f"{[Link]} says Woof!")

def fetch(self): # new method


print(f"{[Link]} fetches the ball!")

class Cat(Animal):
def speak(self):
print(f"{[Link]} says Meow!")

d = Dog("Bruno")
[Link]() # inherited from Animal
[Link]() # overridden — Bruno says Woof!
[Link]() # own method

# super() — call parent's method


class Vehicle:
def __init__(self, brand, speed):
[Link] = brand
[Link] = speed

class Car(Vehicle):
def __init__(self, brand, speed, doors):
super().__init__(brand, speed) # call parent __init__
[Link] = doors

car = Car("Toyota", 180, 4)


print([Link], [Link], [Link])

Encapsulation
class BankAccount:
def __init__(self, owner, balance):
[Link] = owner
self.__balance = balance # private (name mangled)
self._account_no = "12345" # protected (convention)

def deposit(self, amount):


if amount > 0:
self.__balance += amount

def withdraw(self, amount):


if amount <= self.__balance:
self.__balance -= amount
else:
print("Insufficient funds!")

def get_balance(self): # getter


return self.__balance

acc = BankAccount("Ravi", 5000)


[Link](2000)
[Link](1000)
print("Balance:", acc.get_balance()) # 6000
# acc.__balance — AttributeError (private!)

Operator Overloading
class Complex:
def __init__(self, r, i):
self.r = r
self.i = i

def __add__(self, o): # +


return Complex(self.r+o.r, self.i+o.i)

def __sub__(self, o): # -


return Complex(self.r-o.r, self.i-o.i)
def __mul__(self, o): # *
return Complex(self.r*o.r - self.i*o.i,
self.r*o.i + self.i*o.r)

def __eq__(self, o): # ==


return self.r==o.r and self.i==o.i

def __str__(self): # str()


sign = "+" if self.i >= 0 else ""
return f"{self.r}{sign}{self.i}i"

c1 = Complex(3, 4)
c2 = Complex(1, -2)
print(c1 + c2) # 4+2i
print(c1 - c2) # 2+6i
print(c1 == c2) # False

Interview: Q: What is the difference between __str__ and __repr__? __str__ returns a user-friendly string
(print). __repr__ returns an unambiguous developer string (debugging). If __str__ is missing, Python falls back
to __repr__.
Interview: Q: What is multiple inheritance? A class inheriting from more than one parent class. Python resolves
method lookup using MRO (Method Resolution Order) — C3 linearization algorithm.
Chapter 13 — Exception Handling
An exception is an error that occurs during program execution. Python handles exceptions using try-except
blocks to prevent program crashes.

Common Built-in Exceptions


# ZeroDivisionError
10 / 0

# TypeError
"5" + 5

# ValueError
int("abc")

# IndexError
[1,2,3][10]

# KeyError
{"a": 1}["b"]

# FileNotFoundError
open("[Link]")

# AttributeError
(5).upper()

# NameError
print(undefined_var)

# RecursionError — infinite recursion

try / except / else / finally


def safe_divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("Cannot divide by zero!")
return None
except TypeError as e:
print(f"Type error: {e}")
return None
else:
# runs ONLY if no exception
print(f"Result: {result}")
return result
finally:
# ALWAYS runs (cleanup)
print("Operation complete.")

safe_divide(10, 2) # Result: 5.0 / Operation complete.


safe_divide(10, 0) # Cannot divide / Operation complete.
safe_divide(10, "a") # Type error / Operation complete.

# Multiple exceptions in one except


try:
x = int(input("Enter number: "))
print(100 / x)
except (ValueError, ZeroDivisionError) as e:
print(f"Error: {e}")

Raising Custom Exceptions


# Raise built-in exception
def set_age(age):
if age < 0 or age > 150:
raise ValueError(f"Invalid age: {age}")
return age

try:
set_age(-5)
except ValueError as e:
print(e) # Invalid age: -5

# Create custom exception class


class InsufficientFundsError(Exception):
def __init__(self, amount, balance):
[Link] = amount
[Link] = balance
super().__init__(
f"Cannot withdraw {amount}. Balance is only {balance}.")

class BankAccount:
def __init__(self, balance):
[Link] = balance

def withdraw(self, amount):


if amount > [Link]:
raise InsufficientFundsError(amount, [Link])
[Link] -= amount

try:
acc = BankAccount(500)
[Link](1000)
except InsufficientFundsError as e:
print(e)

Interview: Q: What is the purpose of finally? finally block always executes whether or not an exception
occurred. Used for cleanup — closing files, releasing connections.

Interview: Q: Can we have try without except? Yes, try...finally is valid (no except). But try alone is invalid.
Chapter 14 — NumPy Basics
NumPy (Numerical Python) is the foundation library for scientific computing in Python. It provides fast
multi-dimensional arrays and mathematical operations.

Creating Arrays
import numpy as np

# From list
a = [Link]([1, 2, 3, 4, 5])
b = [Link]([[1,2,3],[4,5,6]]) # 2D

# Special arrays
print([Link]((3,3))) # 3x3 matrix of 0s
print([Link]((2,4))) # 2x4 matrix of 1s
print([Link](3)) # 3x3 identity matrix
print([Link](0, 10, 2)) # [0 2 4 6 8]
print([Link](0, 1, 5)) # [0. 0.25 0.5 0.75 1.]
print([Link](1,10,(3,3))) # 3x3 random ints

Array Properties & Operations


a = [Link]([[1,2,3],[4,5,6]])

print([Link]) # (2, 3) — rows x cols


print([Link]) # 2 — dimensions
print([Link]) # 6 — total elements
print([Link]) # int64

# Reshape
b = [Link](1, 13).reshape(3, 4)

# Slicing
print(a[0]) # [1 2 3] — first row
print(a[:, 1]) # [2 5] — second column
print(a[0, 1:]) # [2 3] — row 0, cols 1-end

# Math operations (element-wise)


x = [Link]([1,2,3])
y = [Link]([4,5,6])
print(x + y) # [5 7 9]
print(x * y) # [4 10 18]
print(x ** 2) # [1 4 9]
print([Link](x, y)) # 32 — dot product

# Aggregate
print([Link]()) # 21
print([Link]()) # 3.5
print([Link]()) # 6
print([Link]()) # 1
print([Link](axis=0)) # column sums: [5 7 9]
print([Link](axis=1)) # row sums: [6 15]

Masking & Broadcasting


import numpy as np

# Masking — filter with boolean condition


arr = [Link]([5, 15, 3, 22, 8, 30])
mask = arr > 10
print(mask) # [F T F T F T]
print(arr[mask]) # [15 22 30]

# One-liner
print(arr[arr > 10]) # [15 22 30]

# Broadcasting — operations between different-shaped arrays


a = [Link]([[1,2,3],[4,5,6]]) # shape (2,3)
b = [Link]([10, 20, 30]) # shape (3,)
print(a + b) # b broadcast to each row
# [[11 22 33]
# [14 25 36]]
Chapter 15 — Comprehensions, Lambda & Functional Tools

List Comprehension
A concise way to create lists. Replaces for loops with a single line.
# [expression for item in iterable if condition]

# Squares
squares = [x**2 for x in range(1, 6)]
# [1, 4, 9, 16, 25]

# Even numbers
evens = [x for x in range(1, 21) if x % 2 == 0]

# String operation on list


words = ["hello", "WORLD", "Python"]
upper = [[Link]() for w in words]

# Nested list 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]]

# Flatten a 2D list
flat = [x for row in matrix for x in row]

Dictionary & Set Comprehension


# Dictionary comprehension
squares_dict = {x: x**2 for x in range(1, 6)}
# {1:1, 2:4, 3:9, 4:16, 5:25}

# Invert a dictionary
d = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in [Link]()}
# {1:'a', 2:'b', 3:'c'}

# Set comprehension
unique_sq = {x**2 for x in [-2,-1,0,1,2]}
# {0, 1, 4}

Lambda Functions
A lambda is an anonymous (nameless) single-expression function. Used for short, throwaway functions.
# lambda arguments: expression
square = lambda x: x**2
add = lambda a, b: a + b

print(square(5)) # 25
print(add(3, 4)) # 7

# Use with sorted()


students = [("Ravi",85), ("Priya",92), ("Amit",78)]
[Link](key=lambda x: x[1], reverse=True)
print(students) # sorted by marks descending

# Use with map() — apply function to each element


nums = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x*2, nums))
# [2, 4, 6, 8, 10]

# Use with filter() — keep elements where function returns True


evens = list(filter(lambda x: x%2==0, nums))
# [2, 4]

# reduce() — apply function cumulatively


from functools import reduce
product = reduce(lambda a,b: a*b, [1,2,3,4,5])
print(product) # 120

Interview: Q: When to use lambda vs def? Use lambda for short, one-line anonymous functions passed to
map/filter/sort. Use def for complex, reusable, named functions.
Chapter 16 — Interview Q&A; Quick Reference

Q1. What is Python? Name its key features.


A: Python is a high-level, interpreted, dynamically-typed, general-purpose language. Key features: easy syntax,
cross-platform, huge library, OOP support, garbage collection.

Q2. What is the difference between list, tuple, set, and dict?
A: List: ordered, mutable, allows duplicates []. Tuple: ordered, immutable, allows duplicates (). Set: unordered,
mutable, NO duplicates {}. Dict: key-value pairs, mutable, keys unique {}.

Q3. What are mutable and immutable objects?


A: Mutable: can be changed after creation — list, dict, set. Immutable: cannot be changed — int, float, str, tuple.
Strings are immutable even though they look changeable (they create new objects).

Q4. What is the difference between deep copy and shallow copy?
A: Shallow copy ([Link]): copies object but nested objects are still shared. Deep copy ([Link]):
copies everything recursively — completely independent.

Q5. What is a decorator in Python?


A: A decorator is a function that takes another function as input and extends its behavior without modifying it.
Uses @syntax. Common use: logging, authentication, timing.

Q6. What is a generator?


A: A generator is a function that uses yield instead of return. It produces values one at a time (lazy evaluation),
saving memory. Example: range() is a generator.

Q7. What is the GIL (Global Interpreter Lock)?


A: GIL is a mutex in CPython that allows only one thread to execute Python bytecode at a time. It simplifies
memory management but limits true multi-threading for CPU-bound tasks.

Q8. What is the difference between @staticmethod and @classmethod?


A: @staticmethod: no access to instance or class. @classmethod: gets class as first argument (cls), not
instance (self). Neither can access instance attributes directly.

Q9. What are *args and **kwargs?


A: *args collects extra positional arguments as a tuple. **kwargs collects extra keyword arguments as a
dictionary. They allow functions to accept variable numbers of arguments.

Q10. What is list comprehension and when to use it?


A: A concise one-line way to create lists: [expr for x in iterable if condition]. Use when the logic is simple. Prefer
regular for loops for complex logic for readability.

Q11. What is the difference between append() and extend()?


A: append(x) adds x as a single element to the list. extend(iterable) adds all elements of iterable individually.
[Link]([1,2]) -> [...,[1,2]]. [Link]([1,2]) -> [...,1,2].

Q12. What is __init__ in Python?


A: __init__ is the constructor method called automatically when an object is created. It initializes the object's
attributes. self refers to the current instance.

Q13. What is the difference between is and ==?


A: == compares values (equality). is compares identity (same object in memory). Two lists with same values: ==
is True, is is False unless they are the same object.

Q14. What is exception handling? Why is it needed?


A: Exception handling (try/except) prevents program crashes by catching and handling runtime errors. It
separates error-handling code from normal logic, making programs robust.

Q15. What is inheritance and its types?


A: Inheritance: child class acquires properties of parent. Types: Single (A->B), Multiple (A,B->C), Multilevel
(A->B->C), Hierarchical (A->B, A->C), Hybrid (combination).

Q16. What is polymorphism?


A: Polymorphism means same interface, different behavior. In Python: method overriding (child redefines parent
method), operator overloading (__add__, __str__), duck typing.

Q17. What is encapsulation?


A: Encapsulation bundles data and methods together and restricts direct access. Python uses _name
(protected, convention) and __name (private, name-mangled) for access restriction.

Q18. What are Python's built-in data types?


A: int, float, complex, str, bool, list, tuple, dict, set, frozenset, bytes, bytearray, NoneType.

Q19. What is the difference between range() and xrange()?


A: In Python 3, xrange() doesn't exist — range() itself is lazy (like Python 2's xrange). range() returns a range
object that generates numbers on demand, not a full list.

Q20. What is a lambda function? Give an example.


A: lambda is an anonymous one-line function. Example: square = lambda x: x**2. Used with map(), filter(),
sorted(). Cannot contain statements, only expressions.
Python Complete Reference Notes
Covers: Introduction · Variables · Control Flow · Functions · Strings · Lists · Tuples · Dictionaries ·
Sets · Files · Modules · OOP · Exceptions · NumPy · Comprehensions · Interview Q&A;

Study hard. Code daily. You've got this!

You might also like