0% found this document useful (0 votes)
3 views29 pages

Python Complete Reference

The document is a comprehensive reference guide for Python, covering syntax, common errors, and real-world usage across all core topics from variables to concurrency. It includes detailed sections on data types, operators, functions, conditionals, loops, and more, providing examples and explanations for each concept. The guide aims to help users understand Python thoroughly by encouraging hands-on practice with code examples.

Uploaded by

sambrajyampranay
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)
3 views29 pages

Python Complete Reference

The document is a comprehensive reference guide for Python, covering syntax, common errors, and real-world usage across all core topics from variables to concurrency. It includes detailed sections on data types, operators, functions, conditionals, loops, and more, providing examples and explanations for each concept. The guide aims to help users understand Python thoroughly by encouraging hands-on practice with code examples.

Uploaded by

sambrajyampranay
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: The Complete Reference

Syntax · Every Topic · All Common Errors · Real Usage

Covers exact syntax, common errors with fixes, and real-world use for every core Python topic -- from
variables to concurrency.
Table of Contents

1. Introduction
2. Python Syntax Rules
3. Variables and Memory Model
4. Data Types
5. Operators (Complete)
6. Strings -- Complete Reference
7. Conditionals -- Complete
8. Loops -- Complete
9. Functions -- Complete
10. Lists -- Complete
11. Tuples -- Complete
12. Dictionaries -- Complete
13. Sets -- Complete
14. Errors and Exceptions -- Complete Reference
15. Every Common Error, Explained
16. File Handling -- Complete
17. Modules and Packages -- Complete
18. Object-Oriented Programming -- Complete
19. Iterators and Generators -- Complete
20. Decorators -- Complete
21. Context Managers -- Complete
22. Functional Tools -- map, filter, reduce
23. Regular Expressions (re module)
24. The collections Module
25. Dates and Time
26. Testing and Debugging
27. Concurrency (Threading, Multiprocessing, Async) -- Overview
28. Key Libraries for Real Projects
29. Practice Roadmap
1. Introduction
This is a complete Python reference: every core topic, its exact syntax, common errors you'll hit while using
it, and where it's used in real code. Type every example yourself in Termux -- don't just read.

2. Python Syntax Rules


2.1 Indentation (not braces)
Python uses indentation (spaces) to define code blocks, not {} like C++/Java. This is the single most
common source of errors for beginners coming from other languages.

if True:
print("Indented 4 spaces -- this is a code block")
print("Same block, same indent level")
print("Back to column 0 -- outside the if block")

COMMON ERROR: IndentationError: expected an indented block


Cause: forgetting to indent after a colon (:), or mixing tabs and spaces.
Fix: use 4 spaces consistently, never mix tabs and spaces in the same file.

2.2 Comments
# This is a single-line comment

"""
This is a multi-line comment / docstring
used often at the top of files or functions
"""

x = 5 # inline comment explaining this line

2.3 Statements and line continuation


Normally one statement per line. A semicolon can join two statements on one line (rarely used, not
recommended). A backslash continues a statement onto the next line.

a = 1; b = 2 # works but considered bad style

total = 1 + 2 + 3 + \
4 + 5 + 6 # backslash continuation

total2 = (1 + 2 + 3 +
4 + 5 + 6) # preferred: parentheses continuation

2.4 Keywords (reserved words -- cannot be used as variable names)


False None True and as assert async await
break class continue def del elif else except
finally for from global if import in is
lambda nonlocal not or pass raise return try
while with yield
COMMON ERROR: SyntaxError: invalid syntax
Cause: using a keyword as a variable name, e.g. class = 5, or missing a colon.
Fix: rename the variable, or add the missing : after if/for/while/def/class.

2.5 Identifiers (naming rules)


Must start with a letter or underscore, can contain letters/numbers/underscores, case-sensitive, cannot be a
keyword.

valid_name = 1
_private = 2
name2 = 3
# 2name = 4 -- SyntaxError: invalid syntax (starts with digit)
# my-name = 5 -- SyntaxError (hyphen not allowed)

3. Variables and Memory Model


A variable is a name bound to an object in memory. Python is dynamically typed -- the same name can point
to different types over its lifetime.

name = "Tgr"
age = 20
age = "twenty" # legal in Python -- age now points to a string

x = 5
y = x # y points to the same value 5
print(id(x), id(y)) # id() shows memory address -- same for small ints (cached)

Multiple assignment and unpacking


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

first, *rest = [1, 2, 3, 4] # unpacking with *


print(first) # 1
print(rest) # [2, 3, 4]

x, y = y, x # swap without a temp variable

COMMON ERROR
NameError: name 'x' is not defined
Cause: using a variable before assigning it, or a typo in the name.
Fix: check spelling, and make sure the variable is assigned before use in that scope.

4. Data Types
4.1 Numeric types
a = 42 # int
b = 3.14 # float
c = 2 + 3j # complex
print(type(a), type(b), type(c))

# Number systems
binary = 0b1010 # binary, = 10
octal = 0o12 # octal, = 10
hexa = 0xA # hexadecimal, = 10
print(binary, octal, hexa)

print(bin(10)) # '0b1010'
print(hex(10)) # '0xa'
print(oct(10)) # '0o12'

4.2 Strings, Booleans, NoneType


s = "hello"
b = True
n = None # represents 'no value' -- used as a default/placeholder
print(type(s), type(b), type(n))

if n is None: # always compare None with 'is', not ==


print('n has no value yet')

4.3 Checking and converting types


x = "42"
print(type(x)) # <class 'str'>
print(isinstance(x, str)) # True -- preferred over type() == checks

y = int(x) # "42" -> 42


z = float(x) # "42" -> 42.0
w = str(100) # 100 -> "100"
b = bool(0) # False -- 0, 0.0, "", [], {}, None are all falsy
b2 = bool(5) # True -- any non-zero/non-empty value is truthy

COMMON ERROR: ValueError: invalid literal for int() with base 10: 'abc'
Cause: trying to convert a non-numeric string to int/float.
Fix: validate input first, or wrap the conversion in try/except.

COMMON ERROR: TypeError: unsupported operand type(s) for +: 'int' and 'str'
Cause: mixing incompatible types, e.g. 5 + "5".
Fix: convert explicitly: 5 + int("5") or str(5) + "5".

5. Operators (Complete)
5.1 Arithmetic
+ - * / // % **
print(10 / 3) # 3.333... true division
print(10 // 3) # 3 floor division
print(10 % 3) # 1 modulus/remainder
print(2 ** 10) # 1024 exponent
5.2 Comparison
== != > < >= <=

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

5.4 Bitwise
Used in: low-level flags, permissions systems, competitive programming optimizations.

& | ^ ~ << >>


print(5 & 3) # 1 AND
print(5 | 3) # 7 OR
print(5 ^ 3) # 6 XOR
print(~5) # -6 NOT
print(5 << 1) # 10 left shift (multiply by 2)
print(5 >> 1) # 2 right shift (divide by 2)

5.5 Identity operators (is / is not)


Checks if two names point to the exact same object in memory, not just equal value.

a = [1, 2]
b = [1, 2]
print(a == b) # True -- same value
print(a is b) # False -- different objects in memory

5.6 Membership operators (in / not in)


print(3 in [1, 2, 3]) # True
print("x" not in "abc") # True

5.7 Assignment operators


x = 5
x += 2 # x = x + 2
x -= 1
x *= 3
x /= 2
x //= 2
x **= 2
x %= 4

5.8 Walrus operator (:=) -- Python 3.8+


Assigns and returns a value in the same expression. Used to avoid calling a function twice, common in while
loops and comprehensions.

data = [1, 2, 3, 4, 5]
if (n := len(data)) > 3:
print(f"List has {n} items -- more than 3")
while (line := input("Enter text (or 'q'): ")) != "q":
print("You typed:", line)

5.9 Operator precedence (highest to lowest, key ones)


** exponent
+x, -x, ~x unary
* / // % multiplicative
+ - additive
<< >> shifts
& bitwise AND
^ bitwise XOR
| bitwise OR
== != < > <= >= is in comparisons
not logical NOT
and logical AND
or logical OR

6. Strings -- Complete Reference


6.1 Creating strings, escape sequences
s1 = "double quotes"
s2 = 'single quotes'
s3 = """triple quotes -- can span
multiple lines"""

# Escape sequences
print("Line1\nLine2") # \n = newline
print("Col1\tCol2") # \t = tab
print("She said \"hi\"") # \" = literal quote
print("C:\\path\\file") # \\ = literal backslash

raw = r"C:\path\file" # raw string -- ignores escape sequences


print(raw)

6.2 Indexing and slicing


s = "Hello World"
print(s[0]) # H -- first character
print(s[-1]) # d -- last character
print(s[0:5]) # Hello -- slice, index 0 up to (not including) 5
print(s[6:]) # World -- from index 6 to end
print(s[:5]) # Hello -- from start to index 5
print(s[::-1]) # dlroW olleH -- reversed, step -1
print(s[::2]) # Hlo ol -- every 2nd character

COMMON ERROR: IndexError: string index out of range


Cause: accessing an index that doesn't exist, e.g. s[50] on a 10-char string.
Fix: check len(s) first, or use slicing which never raises this error.

6.3 String methods (most used)


s = " Hello World "
print([Link]()) # removes leading/trailing whitespace
print([Link]()) # left strip only
print([Link]()) # right strip only
print([Link]()) # HELLO WORLD
print([Link]()) # hello world
print([Link]()) # Hello World (each word capitalized)
print([Link]().replace("World", "Python"))
print([Link]().split()) # ['Hello', 'World']
print("-".join(["a", "b", "c"])) # a-b-c
print([Link]().startswith("Hello")) # True
print([Link]().endswith("World")) # True
print([Link]().find("World")) # 6 (index) or -1 if not found
print([Link]().index("World")) # 6, but raises ValueError if not found
print([Link]("l")) # counts occurrences
print("42".isdigit()) # True
print("abc".isalpha()) # True
print("abc123".isalnum()) # True

6.4 String formatting -- 3 ways


name, age = "Tgr", 20

# 1. f-strings (modern, preferred, Python 3.6+)


print(f"{name} is {age} years old")
print(f"{age * 2}") # expressions work directly inside {}
pi = 3.14159
print(f"{pi:.2f}") # 3.14 -- 2 decimal places

# 2. .format() method
print("{} is {} years old".format(name, age))
print("{0} is {1}, again {0}".format(name, age)) # positional reuse

# 3. % formatting (old style, still seen in older codebases)


print("%s is %d years old" % (name, age))

COMMON ERROR: TypeError: can only concatenate str (not "int") to str
Cause: doing "Age: " + 20 directly.
Fix: use f-string f"Age: {20}" or str(20).

7. Conditionals -- Complete
marks = 78
if marks >= 90:
grade = "A"
elif marks >= 75:
grade = "B"
else:
grade = "F"
print(grade)

Ternary expression
status = "adult" if age >= 18 else "minor"
match-case (Python 3.10+, like switch in other languages)
day = 3
match day:
case 1:
print("Monday")
case 2:
print("Tuesday")
case 3 | 4: # matches 3 OR 4
print("Mid-week")
case _: # default case, like else
print("Other day")

COMMON ERROR: SyntaxError: expected ':'


Cause: forgetting the colon after if/elif/else/for/while/def/class.
Fix: every one of these statements must end with a colon before the indented block.

8. Loops -- Complete
8.1 for loop
for i in range(5): # 0 1 2 3 4
print(i)

for i in range(2, 10, 2): # start, stop, step -> 2 4 6 8


print(i)

for ch in "abc":
print(ch) # a b c

8.2 while loop


count = 0
while count < 5:
print(count)
count += 1

8.3 break, continue, pass, and the loop else clause


The else clause on a loop runs only if the loop completes WITHOUT hitting a break. Used for search
patterns -- 'else' means 'not found'.

numbers = [1, 3, 5, 7]
for n in numbers:
if n % 2 == 0:
print("Found an even number")
break
else:
print("No even number found") # this runs since no break happened

8.4 enumerate() -- get index + value together


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

for index, fruit in enumerate(fruits, start=1): # start counting from 1


print(index, fruit)

8.5 zip() -- loop over multiple lists together


names = ["A", "B", "C"]
marks = [80, 90, 70]
for name, mark in zip(names, marks):
print(name, mark)

COMMON ERROR: infinite loop (program never stops / freezes)


Cause: forgetting to update the loop variable in a while loop.
Fix: make sure the condition variable changes inside the loop body, e.g. count += 1.

9. Functions -- Complete
def greet(name):
"""Docstring: explains what the function does."""
return f"Hello, {name}!"

print(greet("Tgr"))
print(greet.__doc__) # prints the docstring

9.1 Default, positional, keyword arguments


def intro(name, age=18, city="Unknown"):
return f"{name}, {age}, {city}"

print(intro("Tgr"))
print(intro("Tgr", 20))
print(intro(name="Tgr", city="Vijayawada")) # keyword args, any order

9.2 *args and **kwargs


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

def show(**kwargs):
for k, v in [Link]():
print(k, v)

print(add_all(1, 2, 3))
show(name="Tgr", age=20)

9.3 Keyword-only arguments


def create_user(name, *, age, city): # everything after * must be passed by keyword
return f"{name}, {age}, {city}"

print(create_user("Tgr", age=20, city="AP"))


# create_user("Tgr", 20, "AP") -- TypeError: takes 1 positional argument
9.4 Lambda functions
square = lambda x: x * x
add = lambda a, b: a + b
print(square(5), add(2, 3))

9.5 Scope: LEGB rule (Local, Enclosing, Global, Built-in)


x = "global"

def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # local
inner()
print(x) # enclosing

outer()
print(x) # global

9.6 global and nonlocal keywords


count = 0
def increment():
global count
count += 1 # modifies the global variable directly

def outer():
x = 10
def inner():
nonlocal x # modifies the enclosing function's variable
x += 1
inner()
print(x) # 11

9.7 Closures
A closure is an inner function that remembers variables from its enclosing scope even after the outer
function has finished. Used in decorators and factory functions.

def make_multiplier(n):
def multiplier(x):
return x * n # remembers "n" even after make_multiplier() returns
return multiplier

times3 = make_multiplier(3)
print(times3(10)) # 30

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

print(factorial(5)) # 120
COMMON ERROR: RecursionError: maximum recursion depth exceeded
Cause: missing or wrong base case, so the function calls itself forever.
Fix: make sure the base case is reachable and correctly stops the recursion.

9.9 Type hints (optional but expected in professional code)


def add(a: int, b: int) -> int:
return a + b

def greet(name: str = "Guest") -> str:


return f"Hello, {name}"

from typing import List, Dict, Optional

def process(items: List[int]) -> Dict[str, int]:


return {"total": sum(items)}

def find_user(uid: int) -> Optional[str]: # may return None


return None

COMMON ERROR: TypeError: greet() missing 1 required positional argument: 'name'


Cause: calling a function without a required argument.
Fix: pass all required arguments, or give the parameter a default value.

10. Lists -- Complete


nums = [5, 2, 8, 1]
[Link](9) # add to end
[Link](0, 100) # insert at index
[Link]([20, 30]) # add multiple items
[Link](2) # remove first matching value
popped = [Link]() # remove & return last item
popped2 = [Link](0) # remove & return item at index 0
[Link]() # sort ascending, in place
[Link](reverse=True) # sort descending
[Link]() # reverse order, in place
print([Link](5)) # count occurrences of 5
print([Link](8)) # index of first occurrence of 8
[Link]() # empty the list

copy1 = [Link]() # shallow copy


copy2 = list(nums) # another way to copy
combined = [1, 2] + [3, 4] # concatenation -> [1,2,3,4]
repeated = [0] * 5 # -> [0,0,0,0,0]
sorted_new = sorted(nums) # returns NEW sorted list, doesn't modify original

COMMON ERROR: IndexError: list index out of range


Cause: accessing nums[10] on a 5-item list.
Fix: check len(nums) before indexing, or use try/except IndexError.

COMMON ERROR: ValueError: [Link](x): x not in list


Cause: calling .remove() with a value that doesn't exist in the list.
Fix: check with 'if x in list' first, or catch the ValueError.
List comprehensions (with condition and nested)
squares = [x*x for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
pairs = [(x, y) for x in range(3) for y in range(2)] # nested loop comprehension
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)] # if/else inline

11. Tuples -- Complete


t = (1, 2, 3)
single = (5,) # a ONE-element tuple needs a trailing comma
not_a_tuple = (5) # this is just an int in parentheses!

print([Link](2)) # counts occurrences


print([Link](3)) # index of value
a, b, c = t # unpacking

COMMON ERROR: TypeError: 'tuple' object does not support item assignment
Cause: trying t[0] = 100 -- tuples are immutable.
Fix: convert to a list first if you need to modify it: list(t).

12. Dictionaries -- Complete


d = {"name": "Tgr", "age": 20}
d["city"] = "AP" # add
d["age"] = 21 # update
del d["city"] # delete a key
removed = [Link]("age") # remove & return value

print([Link]("name")) # safe access


print([Link]("missing", "N/A")) # safe access with default
print([Link]()) # dict_keys(['name'])
print([Link]()) # dict_values(['Tgr'])
print([Link]()) # dict_items([('name', 'Tgr')])

[Link]({"country": "India"}) # merge another dict in


[Link]("status", "active") # sets key only if it doesn't exist

for key, value in [Link]():


print(key, value)

COMMON ERROR: KeyError: 'age'


Cause: accessing d['age'] when the key doesn't exist.
Fix: use [Link]('age') instead, which returns None (or a default) instead of crashing.

Dict comprehension
squares = {x: x*x for x in range(5)}
filtered = {k: v for k, v in [Link]() if v > 5}
13. Sets -- Complete
s = {1, 2, 3}
[Link](4)
[Link](2) # raises KeyError if not present
[Link](10) # does NOT raise error if not present -- safer

a = {1, 2, 3}
b = {2, 3, 4}
print(a | b) # union
print(a & b) # intersection
print(a - b) # difference
print(a ^ b) # symmetric difference (in either, not both)
print([Link](b)) # is a fully contained in b?

unique = set([1, 1, 2, 2, 3]) # removes duplicates -> {1, 2, 3}


squares = {x*x for x in range(5)} # set comprehension

COMMON ERROR: TypeError: unhashable type: 'list'


Cause: trying to put a list inside a set (sets need hashable/immutable elements).
Fix: use a tuple instead of a list if you need to store a sequence in a set.

14. Errors and Exceptions -- Complete Reference


Errors in Python fall into two categories: Syntax Errors (your code isn't valid Python at all, caught before
running) and Exceptions (valid code that fails while running). Knowing the exact error name tells you exactly
what went wrong -- this is one of the most valuable debugging skills you can build.

14.1 Reading a traceback


When Python crashes, it prints a 'traceback' -- read it from the BOTTOM up. The last line names the
exception and the message; the lines above show the call chain that led there.

Traceback (most recent call last):


File "[Link]", line 10, in <module>
result = divide(10, 0)
File "[Link]", line 5, in divide
return a / b
ZeroDivisionError: division by zero

Read this as: 'ZeroDivisionError happened on line 5, inside divide(), which was called from line 10.' Always
start with the exception type on the last line.

14.2 try / except / else / finally -- full syntax


try:
age = int(input("Enter age: "))
result = 100 / age
except ValueError:
print("Not a valid number")
except ZeroDivisionError:
print("Age cannot be zero")
except Exception as e: # catches anything else -- always LAST
print(f"Unexpected error: {e}")
else:
print(f"Result: {result}") # runs ONLY if no exception occurred
finally:
print("Done") # ALWAYS runs, error or not -- cleanup code goes here

14.3 Catching multiple exceptions in one line


try:
x = int("abc")
except (ValueError, TypeError) as e:
print(f"Bad input: {e}")

14.4 Raising exceptions


def withdraw(balance, amount):
if amount < 0:
raise ValueError("Amount cannot be negative")
if amount > balance:
raise ValueError("Insufficient funds")
return balance - amount

try:
withdraw(100, -5)
except ValueError as e:
print(e)

14.5 Custom exceptions


Used in real projects to represent domain-specific errors clearly -- e.g. an e-commerce app might have
OutOfStockError, a banking app InsufficientFundsError.

class InsufficientFundsError(Exception):
"""Raised when a withdrawal exceeds the available balance."""
pass

def withdraw(balance, amount):


if amount > balance:
raise InsufficientFundsError(f"Cannot withdraw {amount}, balance is {balance}")
return balance - amount

try:
withdraw(100, 500)
except InsufficientFundsError as e:
print("Transaction failed:", e)

14.6 The exception hierarchy (key built-in exceptions)


BaseException
+-- SystemExit
+-- KeyboardInterrupt # user pressed Ctrl+C
+-- Exception # base for almost everything you'll catch
+-- ArithmeticError
| +-- ZeroDivisionError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- ValueError
+-- TypeError
+-- NameError
+-- AttributeError
+-- ImportError
| +-- ModuleNotFoundError
+-- OSError
| +-- FileNotFoundError
| +-- PermissionError
+-- StopIteration
+-- RecursionError
+-- MemoryError
+-- NotImplementedError

Because more specific errors inherit from Exception, catching 'except Exception' catches everything below
it. Always catch the MOST SPECIFIC error you expect first, and use a broad 'except Exception' only as a
last-resort catch-all.

15. Every Common Error, Explained


SyntaxError
The code isn't valid Python -- caught before the program even starts running.

if True
print("hi")
# SyntaxError: expected ':' -- missing colon after the if condition

IndentationError
if True:
print("hi")
# IndentationError: expected an indented block -- missing indent after the colon

NameError
print(total)
# NameError: name 'total' is not defined -- used before assignment, or a typo

TypeError
"5" + 5
# TypeError: can only concatenate str (not "int") to str
# Fix: str(5) + "5" or int("5") + 5

ValueError
int("abc")
# ValueError: invalid literal for int() with base 10: 'abc'
# Fix: validate the string is numeric before converting

IndexError
nums = [1, 2, 3]
print(nums[5])
# IndexError: list index out of range

KeyError
d = {"a": 1}
print(d["b"])
# KeyError: 'b' -- Fix: use [Link]('b') instead

AttributeError
x = 5
[Link](3)
# AttributeError: 'int' object has no attribute 'append'
# Cause: calling a method that doesn't exist for that type (append is for lists)

ZeroDivisionError
print(10 / 0)
# ZeroDivisionError: division by zero

ImportError / ModuleNotFoundError
import some_missing_library
# ModuleNotFoundError: No module named 'some_missing_library'
# Fix: pip install some_missing_library

FileNotFoundError
open("[Link]")
# FileNotFoundError: [Errno 2] No such file or directory: '[Link]'

RecursionError
def f():
return f() # no base case
f()
# RecursionError: maximum recursion depth exceeded

StopIteration
it = iter([1, 2])
next(it); next(it); next(it)
# StopIteration -- raised when a generator/iterator has no more values
# (normally handled automatically by for-loops)

KeyboardInterrupt
Raised when the user presses Ctrl+C to stop a running program. Common to catch this in long-running
scripts to shut down cleanly.

try:
while True:
pass
except KeyboardInterrupt:
print("Stopped by user")
16. File Handling -- Complete
16.1 File modes
'r' read (default, error if file doesn't exist)
'w' write (creates file, OVERWRITES if it exists)
'a' append (creates file, adds to end if it exists)
'x' exclusive create (errors if file already exists)
'r+' read and write
'rb', 'wb' binary mode (images, non-text files)

with open("[Link]", "w") as f:


[Link]("Line 1\n")
[Link](["Line 2\n", "Line 3\n"])

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


print([Link]()) # whole file as one string

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


lines = [Link]() # list of lines, each with \n

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


for line in f: # memory-efficient, one line at a time
print([Link]())

COMMON ERROR: FileNotFoundError


Cause: opening a file in 'r' mode that doesn't exist, or wrong path.
Fix: check the path with [Link](path) first, or catch the exception.

16.2 pathlib -- the modern way to handle paths


from pathlib import Path

p = Path("data/[Link]")
print([Link]()) # True/False
print([Link]) # [Link]
print([Link]) # .txt
print([Link]) # data

for file in Path(".").glob("*.py"): # list all .py files in current folder


print(file)

16.3 JSON (used constantly with APIs)


import json

data = {"name": "Tgr", "age": 20, "skills": ["Python", "C++"]}

with open("[Link]", "w") as f:


[Link](data, f, indent=2) # write dict as JSON file

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


loaded = [Link](f) # read JSON file back into a dict

text = [Link](data) # dict -> JSON string


back = [Link](text) # JSON string -> dict
16.4 CSV files
import csv

with open("[Link]", "w", newline="") as f:


writer = [Link](f)
[Link](["name", "marks"])
[Link](["Tgr", 85])

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


reader = [Link](f)
for row in reader:
print(row["name"], row["marks"])

17. Modules and Packages -- Complete


# math_utils.py
def add(a, b):
return a + b

PI = 3.14159

if __name__ == "__main__":
# this block only runs when math_utils.py is run directly,
# NOT when it's imported by another file -- used for quick self-tests
print(add(2, 3))

# [Link]
import math_utils
print(math_utils.add(5, 3))
print(math_utils.PI)

from math_utils import add # import a specific name


from math_utils import add as plus # import with a different name
from math_utils import * # import everything (avoid in real projects)

COMMON ERROR: ModuleNotFoundError: No module named 'math_utils'


Cause: running [Link] from a different folder than math_utils.py.
Fix: run scripts from the same folder, or set up the project as a proper package.

17.1 Installing and managing packages


pip install requests
pip install requests==2.31.0 # specific version
pip install --break-system-packages requests # needed on some Termux setups
pip list # show installed packages
pip freeze > [Link] # save installed packages to a file
pip install -r [Link] # install everything from that file

17.2 Virtual environments


Keeps each project's installed packages separate so different projects don't conflict.

python -m venv myenv


source myenv/bin/activate # Linux/Mac/Termux
myenv\Scripts\activate # Windows
pip install requests
deactivate

17.3 Useful standard library modules


import os # interact with the operating system, file paths, env vars
import sys # command-line arguments, exit the program
import random # random numbers, random choice from a list
import math # sqrt, floor, ceil, pi, trig functions
import time # sleep, measure elapsed time
import datetime # dates and times
import re # regular expressions
import collections # Counter, defaultdict, deque, namedtuple
import itertools # combinations, permutations, infinite iterators
import functools # reduce, lru_cache, wraps

18. Object-Oriented Programming -- Complete


18.1 Class basics
class Student:
school_name = "AP Public School" # class variable -- shared by ALL instances

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


[Link] = name # instance variable -- unique per object
[Link] = marks

def is_passing(self): # instance method


return [Link] >= 40

s1 = Student("Tgr", 78)
s2 = Student("Priya", 30)
print(s1.school_name, s2.school_name) # same for both -- class variable
print(s1.is_passing(), s2.is_passing())

18.2 Instance vs class vs static methods


class Counter:
total = 0

def __init__(self):
[Link] += 1

@classmethod
def get_total(cls): # works on the CLASS, not an instance
return [Link]

@staticmethod
def is_valid_count(n): # doesn't need self or cls -- just a utility
return n >= 0

Counter(); Counter(); Counter()


print(Counter.get_total()) # 3
print(Counter.is_valid_count(-1)) # False
18.3 Inheritance and super()
class Person:
def __init__(self, name):
[Link] = name

def greet(self):
return f"Hi, I am {[Link]}"

class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # calls Person's __init__
[Link] = salary

def greet(self): # method overriding


return f"{super().greet()}, I earn {[Link]}"

e = Employee("Tgr", 50000)
print([Link]())
print(isinstance(e, Person)) # True -- Employee IS-A Person

18.4 Multiple inheritance


class Flyer:
def fly(self):
return "Flying"

class Swimmer:
def swim(self):
return "Swimming"

class Duck(Flyer, Swimmer): # inherits from both


pass

d = Duck()
print([Link](), [Link]())

18.5 Encapsulation (public, protected, private)


class Account:
def __init__(self, balance):
[Link] = balance # public -- accessible anywhere
self._pin = "1234" # protected -- convention: internal use only
self.__secret_key = "xyz" # private -- name-mangled, hardest to access

a = Account(1000)
print([Link]) # works fine
print(a._pin) # works but breaks convention (shouldn't touch it)
# print(a.__secret_key) # AttributeError -- name is mangled to _Account__secret_key

18.6 Polymorphism and abstraction


from abc import ABC, abstractmethod

class Shape(ABC): # abstract base class -- cannot be instantiated


@abstractmethod
def area(self):
pass # forces every subclass to implement this
class Circle(Shape):
def __init__(self, radius):
[Link] = radius

def area(self):
return 3.14159 * [Link] ** 2

class Square(Shape):
def __init__(self, side):
[Link] = side

def area(self):
return [Link] ** 2

shapes = [Circle(5), Square(4)]


for s in shapes:
print([Link]()) # each shape computes area its own way

# Shape() -- TypeError: Can't instantiate abstract class Shape

18.7 Properties (@property) -- controlled attribute access


Lets a method be accessed like a plain attribute, useful for validation or computed values.

class Circle:
def __init__(self, radius):
self._radius = radius

@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): # computed, read-only property
return 3.14159 * self._radius ** 2

c = Circle(5)
print([Link]) # 5 -- accessed like an attribute, not [Link]()
[Link] = 10 # calls the setter, runs validation
print([Link])

18.8 Dunder (magic) methods -- full common set


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

def __str__(self): # print(obj) / str(obj) -- human-readable


return f"({self.x}, {self.y})"

def __repr__(self): # developer-facing representation, used in debugging


return f"Point({self.x}, {self.y})"
def __eq__(self, other): # controls ==
return self.x == other.x and self.y == other.y

def __add__(self, other): # controls +


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

def __len__(self): # controls len(obj)


return 2

def __lt__(self, other): # controls < , used by sort()


return (self.x**2 + self.y**2) < (other.x**2 + other.y**2)

p1, p2 = Point(1, 2), Point(3, 4)


print(p1 + p2) # (4, 6)
print(p1 == Point(1, 2)) # True

18.9 Dataclasses (Python 3.7+) -- less boilerplate


Automatically generates __init__, __repr__, and __eq__ for simple data-holding classes.

from dataclasses import dataclass

@dataclass
class Student:
name: str
marks: int
city: str = "Unknown" # default value

s = Student("Tgr", 85)
print(s) # Student(name='Tgr', marks=85, city='Unknown')
print(s == Student("Tgr", 85)) # True -- __eq__ generated automatically

19. Iterators and Generators -- Complete


19.1 The iterator protocol
nums = [1, 2, 3]
it = iter(nums) # get an iterator from an iterable
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# print(next(it)) -- StopIteration, no more items

class CountUpTo: # a custom iterator class


def __init__(self, limit):
[Link] = limit
self.n = 0

def __iter__(self):
return self

def __next__(self):
if self.n >= [Link]:
raise StopIteration
self.n += 1
return self.n

for num in CountUpTo(5):


print(num)

19.2 Generators (yield) -- the simpler way


def count_up_to(limit):
n = 1
while n <= limit:
yield n # pauses here, resumes on next call
n += 1

for num in count_up_to(5):


print(num)

gen = (x*x for x in range(1000000)) # generator expression -- lazy, memory-safe


print(next(gen))

20. Decorators -- Complete


import functools

def timer(func):
@[Link](func) # preserves original function's name/docstring
def wrapper(*args, **kwargs):
import time
start = [Link]()
result = func(*args, **kwargs)
print(f"{func.__name__} took {[Link]()-start:.4f}s")
return result
return wrapper

@timer
def slow():
import time; [Link](1)

slow()

Decorators that take arguments


def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorator

@repeat(3)
def say_hi():
print("Hi")

say_hi() # prints "Hi" 3 times


21. Context Managers -- Complete
class ManagedFile:
def __init__(self, filename):
[Link] = filename

def __enter__(self):
[Link] = open([Link], "w")
return [Link]

def __exit__(self, exc_type, exc_value, traceback):


[Link]() # always runs, even if an error happened inside

with ManagedFile("[Link]") as f:
[Link]("hello")

# Simpler way using contextlib


from contextlib import contextmanager

@contextmanager
def managed_file(filename):
f = open(filename, "w")
try:
yield f
finally:
[Link]()

with managed_file("[Link]") as f:
[Link]("hello")

22. Functional Tools -- map, filter, reduce


nums = [1, 2, 3, 4, 5]

doubled = list(map(lambda x: x*2, nums))


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

evens = list(filter(lambda x: x % 2 == 0, nums))


print(evens) # [2, 4]

from functools import reduce


total = reduce(lambda a, b: a + b, nums)
print(total) # 15

from functools import lru_cache

@lru_cache(maxsize=None) # caches results -- speeds up repeated calls


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

print(fib(30)) # fast, thanks to caching


23. Regular Expressions (re module)
Used for: validating input (emails, phone numbers), searching/extracting patterns from text, log file parsing,
web scraping cleanup.

import re

text = "Contact: tgr@[Link] or 9876543210"

email = [Link](r"[\w.]+@[\w.]+", text)


print([Link]()) # tgr@[Link]

phone = [Link](r"\d{10}", text)


print(phone) # ['9876543210']

cleaned = [Link](r"\d", "", text) # remove all digits


print(cleaned)

if [Link](r"^[A-Za-z]+$", "Hello"): # matches from the START


print("Only letters")

Common patterns: \d digit, \w word character, \s whitespace, + one-or-more, * zero-or-more, ? optional, ^


start, $ end, [] character set.

24. The collections Module


from collections import Counter, defaultdict, namedtuple, deque

words = ["cat", "dog", "cat", "bird", "dog", "cat"]


print(Counter(words)) # Counter({'cat': 3, 'dog': 2, 'bird': 1})
print(Counter(words).most_common(2)) # top 2 most frequent

graph = defaultdict(list) # auto-creates a default value for missing keys


graph["A"].append("B") # no KeyError even though "A" wasn't set first

Point = namedtuple("Point", ["x", "y"]) # lightweight class-like tuple


p = Point(1, 2)
print(p.x, p.y)

queue = deque([1, 2, 3]) # fast append/pop from BOTH ends


[Link](0)
[Link](4)
print(queue) # deque([0, 1, 2, 3, 4])

25. Dates and Time


from datetime import datetime, timedelta

now = [Link]()
print(now)
print([Link]("%Y-%m-%d %H:%M:%S")) # format as string
parsed = [Link]("2026-07-16", "%Y-%m-%d") # string to datetime

tomorrow = now + timedelta(days=1)


print(tomorrow)

26. Testing and Debugging


26.1 assert -- quick sanity checks
def add(a, b):
return a + b

assert add(2, 3) == 5, "add() is broken" # raises AssertionError if False

26.2 pytest -- the standard testing framework


# test_math.py
def add(a, b):
return a + b

def test_add_positive():
assert add(2, 3) == 5

def test_add_negative():
assert add(-1, -1) == -2

# Run with: pytest test_math.py -v

26.3 Debugging with print and pdb


import pdb

def buggy_function(x):
pdb.set_trace() # execution pauses here -- drops into interactive debugger
return x * 2

# pdb commands once paused: n (next line), c (continue), p x (print x), q (quit)

26.4 Logging (better than scattering print statements)


import logging

[Link](level=[Link])
[Link]("Detailed info, hidden by default")
[Link]("General info")
[Link]("Something looks off")
[Link]("Something failed")

27. Concurrency (Threading, Multiprocessing, Async) --


Overview
Used when a program needs to do multiple things at once -- download several files in parallel, handle many
web requests, or run CPU-heavy work faster.

import threading

def worker(n):
print(f"Worker {n} running")

threads = [[Link](target=worker, args=(i,)) for i in range(3)]


for t in threads: [Link]()
for t in threads: [Link]() # wait for all to finish

# asyncio -- for I/O-heavy tasks like network requests


import asyncio

async def fetch_data():


print("Fetching...")
await [Link](1) # simulates waiting on a network call
print("Done")

[Link](fetch_data())

Rule of thumb: threading for I/O-bound tasks, multiprocessing for CPU-bound tasks (Python's GIL limits true
parallel CPU work in threads), asyncio for many concurrent network/IO operations without the overhead of
real threads.

28. Key Libraries for Real Projects


import numpy as np
arr = [Link]([1, 2, 3])
print(arr * 2, [Link]())

import pandas as pd
df = [Link]({"name": ["A", "B"], "marks": [80, 60]})
print(df[df["marks"] > 70])

import requests
r = [Link]("[Link]
print(r.status_code, [Link]())

from sklearn.linear_model import LinearRegression


model = LinearRegression()
# [Link](X_train, y_train)
# [Link](X_test)

29. Practice Roadmap


Week 1: Syntax, variables, data types, operators, strings.
Week 2: Conditionals, loops, error handling basics -- solve 20 easy problems.
Week 3: Functions, closures, decorators -- rewrite earlier scripts using functions.
Week 4: Lists, tuples, dicts, sets, comprehensions -- build a contact book / grade tracker.
Week 5: File handling, JSON, CSV, custom exceptions -- make the tracker save/load data.
Week 6: Full OOP -- rebuild the tracker using classes, properties, and inheritance.
Week 7: Iterators, generators, context managers, regex.
Week 8: collections module, datetime, testing with pytest, basic logging.
After week 8: NumPy, Pandas, and into ML basics -- this slots into your 60-day and 12-15 month plans
already in place.

You might also like