A comprehensive, beginner-to-advanced reference for learning Python β from your first
print("Hello, World!")to building real-world applications.
Python is a high-level, interpreted, general-purpose programming language created by Guido van Rossum and first released in 1991. Its design philosophy emphasizes code readability with the use of significant indentation.
Python is:
- Interpreted β runs line by line, no compilation needed
- Dynamically typed β variable types are determined at runtime
- Multi-paradigm β supports procedural, OOP, and functional styles
- Batteries included β a rich standard library ships with it
| Use Case | Examples |
|---|---|
| Web Development | Django, Flask, FastAPI |
| Data Science | NumPy, Pandas, SciPy |
| Machine Learning / AI | TensorFlow, PyTorch, scikit-learn |
| Automation & Scripting | Selenium, PyAutoGUI |
| DevOps / Cloud | Ansible, Boto3 (AWS) |
| Game Development | Pygame |
| Cybersecurity | Scapy, pwntools |
Python consistently ranks #1 or #2 on language popularity indices (TIOBE, Stack Overflow surveys) and is the most recommended first language for beginners.
Windows / macOS / Linux:
- Go to https://www.python.org/downloads/
- Download the latest stable release (Python 3.12+)
- During installation on Windows, β check "Add Python to PATH"
Verify installation:
python --version
# Python 3.12.x
pip --version
# pip 24.xπ‘ Tip: Use pyenv to manage multiple Python versions on the same machine.
# hello.py
print("Hello, World!")Run it:
python hello.py
# Hello, World!Python has no explicit type declaration. Variables are created on assignment.
# Integer
age = 25
# Float
price = 19.99
# String
name = "Alice"
# Boolean
is_active = True
# NoneType
result = None
# Check type
print(type(age)) # <class 'int'>
print(type(price)) # <class 'float'>
print(type(name)) # <class 'str'>
print(type(is_active))# <class 'bool'>Multiple assignment:
x = y = z = 0 # All three point to 0
a, b, c = 1, 2, 3 # Unpacking
first, *rest = [1, 2, 3, 4] # Star unpacking β first=1, rest=[2,3,4]# Implicit
result = 5 + 2.0 # β 7.0 (int promoted to float)
# Explicit (casting)
int("42") # β 42
float("3.14") # β 3.14
str(100) # β "100"
bool(0) # β False
bool("hello") # β True
list("abc") # β ['a', 'b', 'c']# Output
print("Hello") # Hello
print("a", "b", "c", sep="-") # a-b-c
print("no newline", end="") # prints without newline
# Input (always returns a string)
name = input("Enter your name: ")
age = int(input("Enter your age: ")) # cast to int# Single-line comment
"""
Multi-line comment (technically a string literal,
but commonly used as a block comment or docstring)
"""
def greet(name):
"""
Docstring: describes the function.
Args:
name (str): the person's name
Returns:
str: greeting message
"""
return f"Hello, {name}!"a, b = 10, 3
a + b # 13 β Addition
a - b # 7 β Subtraction
a * b # 30 β Multiplication
a / b # 3.333... β Division (always float)
a // b # 3 β Floor division
a % b # 1 β Modulo (remainder)
a ** b # 1000 β Exponentiation5 == 5 # True β Equal
5 != 4 # True β Not equal
5 > 3 # True β Greater than
5 < 3 # False β Less than
5 >= 5 # True β Greater than or equal
5 <= 4 # False β Less than or equalTrue and False # False
True or False # True
not True # False
# Short-circuit evaluation
x = None
y = x or "default" # y = "default" (x is falsy)x = 10
x += 5 # x = 15
x -= 3 # x = 12
x *= 2 # x = 24
x //= 5 # x = 4
x **= 2 # x = 16
x %= 5 # x = 1a = 0b1010 # 10
b = 0b1100 # 12
a & b # 0b1000 β 8 (AND)
a | b # 0b1110 β 14 (OR)
a ^ b # 0b0110 β 6 (XOR)
~a # -11 (NOT)
a << 1 # 0b10100β 20 (Left shift)
a >> 1 # 0b0101 β 5 (Right shift)score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print(f"Grade: {grade}") # Grade: BTernary (one-line if):
status = "adult" if age >= 18 else "minor"# Iterate over a list
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# Range
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 10, 2): # 2, 4, 6, 8
print(i)
# Enumerate (index + value)
for i, fruit in enumerate(fruits, start=1):
print(f"{i}. {fruit}")
# Zip (parallel iteration)
names = ["Alice", "Bob"]
scores = [95, 87]
for name, score in zip(names, scores):
print(f"{name}: {score}")count = 0
while count < 5:
print(count)
count += 1
# Infinite loop with break
while True:
user_input = input("Type 'quit' to exit: ")
if user_input == "quit":
breakfor i in range(10):
if i == 3:
continue # Skip 3
if i == 7:
break # Stop at 7
print(i) # Prints: 0 1 2 4 5 6
# pass β a no-op placeholder
def future_function():
pass # TODO: implement later# Basic
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
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
# Dictionary comprehension
word_lengths = {word: len(word) for word in ["python", "is", "fun"]}
# {'python': 6, 'is': 2, 'fun': 3}
# Set comprehension
unique_chars = {c for c in "hello world" if c != " "}
# Generator expression (memory-efficient)
total = sum(x**2 for x in range(1000))def add(a, b):
"""Returns the sum of a and b."""
return a + b
result = add(3, 4) # 7# Default arguments
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
greet("Alice") # "Hello, Alice!"
greet("Bob", "Hi") # "Hi, Bob!"
# Keyword arguments
greet(greeting="Hey", name="Carol")
# *args β variable positional arguments
def total(*args):
return sum(args)
total(1, 2, 3, 4) # 10
# **kwargs β variable keyword arguments
def describe(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
describe(name="Alice", age=30, city="Delhi")
# Positional-only (/) and keyword-only (*) parameters
def strict(pos_only, /, normal, *, kw_only):
pass# Anonymous, single-expression functions
square = lambda x: x ** 2
square(5) # 25
# Common use: sorting
people = [{"name": "Bob", "age": 30}, {"name": "Alice", "age": 25}]
people.sort(key=lambda p: p["age"])
# With map, filter, reduce
nums = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, nums))
evens = list(filter(lambda x: x % 2 == 0, nums))def factorial(n):
if n <= 1: # Base case
return 1
return n * factorial(n - 1) # Recursive case
factorial(5) # 120
# Fibonacci with memoization
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)import time
def timer(func):
"""Measures execution time of a function."""
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f}s")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "done"
slow_function() # slow_function took 1.0001s
# Stacking decorators
@timer
@lru_cache(maxsize=128)
def expensive_calc(n):
return sum(range(n))# Creation
fruits = ["apple", "banana", "cherry"]
empty = []
mixed = [1, "two", 3.0, True]
# Indexing & Slicing
fruits[0] # "apple"
fruits[-1] # "cherry"
fruits[1:3] # ["banana", "cherry"]
fruits[::-1] # Reversed: ["cherry", "banana", "apple"]
# Common methods
fruits.append("date") # Add to end
fruits.insert(1, "avocado") # Insert at index
fruits.remove("banana") # Remove first occurrence
popped = fruits.pop() # Remove & return last
fruits.sort() # In-place sort
fruits.sort(reverse=True) # Descending
sorted_copy = sorted(fruits) # Returns new sorted list
fruits.reverse() # Reverse in-place
fruits.index("apple") # Find index
fruits.count("apple") # Count occurrences
fruits.extend(["elderberry"]) # Merge lists
len(fruits) # Length
"apple" in fruits # Membership test# Immutable sequences
point = (3, 4)
single = (42,) # Note the trailing comma!
packed = 1, 2, 3 # Parentheses optional
# Unpacking
x, y = point
a, b, *rest = (1, 2, 3, 4, 5) # a=1, b=2, rest=[3,4,5]
# Named tuples (readable records)
from collections import namedtuple
Person = namedtuple("Person", ["name", "age", "city"])
alice = Person("Alice", 30, "Delhi")
alice.name # "Alice"# Unordered collection of unique elements
fruits = {"apple", "banana", "cherry", "apple"} # {"apple","banana","cherry"}
empty_set = set() # {} creates a dict, not a set!
# Operations
fruits.add("date")
fruits.discard("banana") # No error if missing
fruits.remove("cherry") # Raises KeyError if missing
# Set math
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # Union: {1,2,3,4,5,6}
a & b # Intersection: {3,4}
a - b # Difference: {1,2}
a ^ b # Symmetric difference: {1,2,5,6}
a <= b # Subset check# Key-value pairs (ordered since Python 3.7+)
person = {"name": "Alice", "age": 30, "city": "Delhi"}
# Access
person["name"] # "Alice"
person.get("phone", "N/A") # "N/A" (safe, no KeyError)
# Modify
person["age"] = 31
person["email"] = "alice@example.com"
del person["city"]
# Iteration
for key in person: # Keys
for value in person.values(): # Values
for key, value in person.items():# Key-value pairs
# Useful methods
person.keys()
person.values()
person.items()
person.update({"age": 32, "phone": "9876543210"})
person.pop("email", None) # Remove & return; None if missing
person.setdefault("city", "Mumbai") # Set only if key absent
# Dictionary comprehension
squares = {n: n**2 for n in range(1, 6)}
# Merging (Python 3.9+)
merged = dict1 | dict2# Stack (LIFO) β use a list
stack = []
stack.append(1) # push
stack.append(2)
stack.pop() # pop β 2
# Queue (FIFO) β use deque for O(1) pops from left
from collections import deque
queue = deque()
queue.append("first")
queue.append("second")
queue.popleft() # β "first"
# Priority Queue
import heapq
pq = []
heapq.heappush(pq, (2, "low priority"))
heapq.heappush(pq, (1, "high priority"))
heapq.heappop(pq) # β (1, "high priority")s = " Hello, Python World! "
s.strip() # Remove whitespace: "Hello, Python World!"
s.lstrip() / s.rstrip()
s.lower() # " hello, python world! "
s.upper() # " HELLO, PYTHON WORLD! "
s.title() # " Hello, Python World! "
s.replace("Python", "Amazing")
s.split(", ") # [" Hello", "Python World! "]
s.split() # Split on whitespace (strips too)
",".join(["a","b","c"]) # "a,b,c"
s.startswith(" He") # True
s.endswith("! ") # True
s.find("Python") # 9 (index) or -1 if not found
s.count("l") # 3
s.isdigit() # False
s.isalpha() # False
s.isalnum() # False
s.center(30, "*") # Center with paddingname, age = "Alice", 30
# f-strings (Python 3.6+) β preferred
f"Name: {name}, Age: {age}"
f"Pi is approximately {3.14159:.2f}"
f"{'title':^20}" # Centered in 20 chars
f"{1000000:,}" # "1,000,000"
# .format()
"Hello, {}! You are {} years old.".format(name, age)
"{name} is {age}".format(name="Bob", age=25)
# % formatting (legacy)
"Hello, %s! Age: %d" % (name, age)
# Multi-line f-string
message = (
f"Name: {name}\n"
f"Age: {age}\n"
)import re
text = "My email is alice@example.com and phone is +91-9876543210"
# Search
match = re.search(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', text)
if match:
print(match.group()) # alice@example.com
# Find all
re.findall(r'\d+', text) # ['91', '9876543210']
# Replace
clean = re.sub(r'\s+', ' ', "too many spaces")
# Compile for repeated use
email_pattern = re.compile(r'[\w.+-]+@[\w-]+\.[\w.]+')
emails = email_pattern.findall(text)
# Groups
date_match = re.search(r'(\d{4})-(\d{2})-(\d{2})', "Born: 1994-07-15")
year, month, day = date_match.groups()class Dog:
# Class variable (shared by all instances)
species = "Canis lupus familiaris"
def __init__(self, name, age): # Constructor
self.name = name # Instance variable
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
def __str__(self): # String representation
return f"Dog(name={self.name}, age={self.age})"
def __repr__(self):
return f"Dog({self.name!r}, {self.age!r})"
@classmethod
def from_birth_year(cls, name, birth_year):
return cls(name, 2024 - birth_year)
@staticmethod
def is_adult(age):
return age >= 2
# Usage
rex = Dog("Rex", 3)
print(rex.bark()) # Rex says: Woof!
print(rex) # Dog(name=Rex, age=3)
print(Dog.species) # Canis lupus familiaris
buddy = Dog.from_birth_year("Buddy", 2020)
Dog.is_adult(3) # Trueclass Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclasses must implement speak()")
def __str__(self):
return f"{type(self).__name__}({self.name})"
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
class GuideDog(Dog):
"""Multiple levels of inheritance."""
def __init__(self, name, owner):
super().__init__(name) # Call parent __init__
self.owner = owner
def speak(self):
base = super().speak()
return f"{base} (Guide dog for {self.owner})"
# Polymorphism
animals = [Dog("Rex"), Cat("Whiskers"), GuideDog("Buddy", "Alice")]
for animal in animals:
print(animal.speak())
# isinstance / issubclass
isinstance(rex, Dog) # True
isinstance(rex, Animal) # True
issubclass(Dog, Animal) # Trueclass BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self._balance = balance # "protected" (convention)
self.__pin = "1234" # "private" (name-mangled)
@property
def balance(self):
"""Getter."""
return self._balance
@balance.setter
def balance(self, amount):
"""Setter with validation."""
if amount < 0:
raise ValueError("Balance cannot be negative")
self._balance = amount
def deposit(self, amount):
if amount > 0:
self._balance += amount
def withdraw(self, amount):
if amount > self._balance:
raise ValueError("Insufficient funds")
self._balance -= amount
account = BankAccount("Alice", 1000)
account.deposit(500)
print(account.balance) # 1500
account.balance = 2000 # Uses setterclass Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __len__(self):
return 2
def __getitem__(self, index):
return (self.x, self.y)[index]
def __iter__(self):
yield self.x
yield self.y
def __repr__(self):
return f"Vector({self.x}, {self.y})"
def __abs__(self):
return (self.x**2 + self.y**2) ** 0.5
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(abs(v2)) # 5.0
print(list(v1)) # [1, 2]import math # Import whole module
from math import sqrt, pi # Import specific names
from math import sqrt as sq # Alias
import numpy as np # Common alias convention
math.sqrt(16) # 4.0
sqrt(25) # 5.0
sq(9) # 3.0# myutils.py
def add(a, b):
return a + b
def multiply(a, b):
return a * b
CONSTANT = 42
if __name__ == "__main__":
# Code here only runs when executed directly, not on import
print("Running myutils directly")# main.py
import myutils
from myutils import add, CONSTANT
result = myutils.multiply(3, 4)
print(add(2, 3)) # 5
print(CONSTANT) # 42| Module | Purpose |
|---|---|
os |
OS interaction, file paths |
sys |
Python interpreter settings |
pathlib |
Object-oriented file paths |
datetime |
Dates and times |
collections |
deque, Counter, defaultdict |
itertools |
Efficient iteration tools |
functools |
Higher-order functions, lru_cache |
json |
JSON encoding/decoding |
re |
Regular expressions |
math |
Math functions |
random |
Random number generation |
time |
Time access and conversions |
threading |
Thread-based parallelism |
subprocess |
Run external commands |
logging |
Logging infrastructure |
unittest |
Unit testing framework |
from collections import Counter, defaultdict
from itertools import chain, combinations, product
import datetime
# Counter
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
count = Counter(words)
count.most_common(2) # [('apple', 3), ('banana', 2)]
# defaultdict
dd = defaultdict(list)
dd["fruits"].append("apple") # No KeyError
# datetime
now = datetime.datetime.now()
today = datetime.date.today()
delta = datetime.timedelta(days=7)
next_week = today + delta# Install a package
pip install requests
# Install specific version
pip install requests==2.31.0
# Install from requirements file
pip install -r requirements.txt
# List installed packages
pip list
pip freeze > requirements.txt
# Create a virtual environment
python -m venv venv
# Activate
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Deactivate
deactivateπ‘ Best Practice: Always use a virtual environment per project to avoid dependency conflicts.
# Writing a file
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Line 1\n")
f.writelines(["Line 2\n", "Line 3\n"])
# Reading a file
with open("output.txt", "r", encoding="utf-8") as f:
content = f.read() # Entire file as string
with open("output.txt", "r") as f:
lines = f.readlines() # List of lines
with open("output.txt", "r") as f:
for line in f: # Memory-efficient iteration
print(line.strip())
# Append
with open("output.txt", "a") as f:
f.write("Line 4\n")
# File modes: 'r' read | 'w' write | 'a' append | 'b' binary | '+' updateimport csv
import json
# CSV write
with open("data.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age"])
writer.writeheader()
writer.writerows([{"name": "Alice", "age": 30}, {"name": "Bob", "age": 25}])
# CSV read
with open("data.csv") as f:
reader = csv.DictReader(f)
for row in reader:
print(row["name"], row["age"])
# JSON write
data = {"name": "Alice", "scores": [95, 87, 92]}
with open("data.json", "w") as f:
json.dump(data, f, indent=2)
# JSON read
with open("data.json") as f:
loaded = json.load(f)
# String conversions
json_str = json.dumps(data) # dict β JSON string
parsed = json.loads('{"x": 1}') # JSON string β dictfrom pathlib import Path
# Create path objects
home = Path.home()
project = Path("my_project")
config = project / "config" / "settings.json"
# Operations
config.parent # Path("my_project/config")
config.name # "settings.json"
config.stem # "settings"
config.suffix # ".json"
# Filesystem
config.exists()
config.is_file()
config.is_dir()
config.parent.mkdir(parents=True, exist_ok=True)
config.write_text('{"debug": true}')
content = config.read_text()
# Glob
for py_file in project.rglob("*.py"):
print(py_file)def safe_divide(a, b):
try:
result = a / b
except ZeroDivisionError:
print("Error: Cannot divide by zero")
return None
except TypeError as e:
print(f"Type error: {e}")
return None
else:
print("Division succeeded!") # Runs only if no exception
return result
finally:
print("This always runs") # Cleanup
safe_divide(10, 2) # 5.0 + messages
safe_divide(10, 0) # None + messages
# Catching multiple exceptions
try:
risky_operation()
except (ValueError, KeyError) as e:
print(f"Caught: {e}")
# Catching any exception
try:
risky_operation()
except Exception as e:
print(f"Unexpected error: {type(e).__name__}: {e}")
raise # Re-raise the exceptiondef set_age(age):
if not isinstance(age, int):
raise TypeError(f"Age must be int, got {type(age).__name__}")
if age < 0 or age > 150:
raise ValueError(f"Age {age} is out of valid range (0β150)")
return age
# Exception chaining
try:
int("not a number")
except ValueError as e:
raise RuntimeError("Failed to parse config") from eclass AppError(Exception):
"""Base exception for this application."""
pass
class ValidationError(AppError):
def __init__(self, field, message):
self.field = field
self.message = message
super().__init__(f"Validation failed on '{field}': {message}")
class DatabaseError(AppError):
pass
# Usage
try:
raise ValidationError("email", "Invalid format")
except ValidationError as e:
print(e.field) # email
print(e.message) # Invalid format
print(e) # Validation failed on 'email': Invalid format# Any object with __iter__ and __next__
class Countdown:
def __init__(self, start):
self.current = start
def __iter__(self):
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
self.current -= 1
return self.current + 1
for num in Countdown(5):
print(num) # 5 4 3 2 1
# Built-in iterators
it = iter([1, 2, 3])
next(it) # 1
next(it) # 2def fibonacci():
"""Infinite Fibonacci generator."""
a, b = 0, 1
while True:
yield a
a, b = b, a + b
gen = fibonacci()
[next(gen) for _ in range(10)]
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
def read_large_file(filepath):
"""Memory-efficient file reader."""
with open(filepath) as f:
for line in f:
yield line.strip()
# Generator pipeline
def integers_from(n):
while True:
yield n
n += 1
def take(n, iterable):
for i, item in enumerate(iterable):
if i >= n:
break
yield item
list(take(5, integers_from(10))) # [10, 11, 12, 13, 14]def batch_processor(data, batch_size=3):
"""Yields data in chunks."""
batch = []
for item in data:
batch.append(item)
if len(batch) == batch_size:
yield batch
batch = []
if batch:
yield batch
for batch in batch_processor(range(10), 3):
print(batch)
# [0, 1, 2]
# [3, 4, 5]
# [6, 7, 8]
# [9]
# yield from β delegate to sub-generator
def chain(*iterables):
for it in iterables:
yield from it
list(chain([1, 2], [3, 4], [5])) # [1, 2, 3, 4, 5]import threading
import time
def download(url):
print(f"Downloading {url}...")
time.sleep(2) # Simulate network I/O
print(f"Done: {url}")
urls = ["url1.com", "url2.com", "url3.com"]
threads = [threading.Thread(target=download, args=(url,)) for url in urls]
for t in threads:
t.start()
for t in threads:
t.join() # Wait for all to finish
print("All downloads complete")
# Thread-safe data with Lock
counter = 0
lock = threading.Lock()
def increment():
global counter
with lock:
counter += 1from multiprocessing import Pool
import os
def cpu_bound_task(n):
return sum(i * i for i in range(n))
# Use all CPU cores
with Pool(processes=os.cpu_count()) as pool:
results = pool.map(cpu_bound_task, [10**6, 10**6, 10**6, 10**6])
print(results)π‘ Rule of thumb: Use
threadingfor I/O-bound tasks;multiprocessingfor CPU-bound tasks. The Python GIL limits true thread parallelism for CPU work.
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
urls = [
"https://api.github.com",
"https://httpbin.org/get",
]
async with aiohttp.ClientSession() as session:
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
return results
asyncio.run(main())
# Simple async example
async def greet(name, delay):
await asyncio.sleep(delay)
print(f"Hello, {name}!")
async def run():
await asyncio.gather(
greet("Alice", 2),
greet("Bob", 1),
greet("Carol", 0.5),
)
asyncio.run(run())
# Hello, Carol! (after 0.5s)
# Hello, Bob! (after 1s)
# Hello, Alice! (after 2s)import numpy as np
# Arrays
a = np.array([1, 2, 3, 4, 5])
b = np.zeros((3, 3))
c = np.ones((2, 4))
d = np.arange(0, 10, 2) # [0 2 4 6 8]
e = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ]
# Operations (vectorized, very fast)
a * 2 # [2 4 6 8 10]
a ** 2 # [1 4 9 16 25]
np.sqrt(a)
# 2D arrays
matrix = np.array([[1, 2], [3, 4]])
matrix.T # Transpose
np.dot(matrix, matrix) # Matrix multiply (or @)
matrix @ matrix
matrix.shape # (2, 2)
matrix.reshape(1, 4) # [[1 2 3 4]]
np.mean(matrix, axis=0) # Column meansimport pandas as pd
# DataFrame creation
df = pd.DataFrame({
"name": ["Alice", "Bob", "Carol"],
"age": [25, 30, 35],
"score": [88, 92, 79]
})
# Basic exploration
df.head(2)
df.info()
df.describe()
df.shape # (3, 3)
# Selecting
df["name"] # Series
df[["name", "score"]] # DataFrame
df[df["age"] > 25] # Filter
df.loc[0, "name"] # Label-based
df.iloc[0, 0] # Position-based
# Operations
df["score_pct"] = df["score"] / 100 # New column
df.sort_values("age", ascending=False)
df.groupby("age").mean(numeric_only=True)
df.dropna() # Remove NaN rows
df.fillna(0)
# I/O
df.to_csv("data.csv", index=False)
df = pd.read_csv("data.csv")
df.to_excel("data.xlsx", index=False)import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 2 * np.pi, 100)
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Line plot
axes[0].plot(x, np.sin(x), label="sin(x)", color="blue")
axes[0].plot(x, np.cos(x), label="cos(x)", color="red", linestyle="--")
axes[0].set_title("Trigonometric Functions")
axes[0].legend()
axes[0].grid(True)
# Bar chart
categories = ["A", "B", "C", "D"]
values = [23, 45, 12, 67]
axes[1].bar(categories, values, color="steelblue")
axes[1].set_title("Category Comparison")
axes[1].set_ylabel("Value")
plt.tight_layout()
plt.savefig("plot.png", dpi=150)
plt.show()import requests
# GET request
response = requests.get("https://api.github.com/users/python")
response.status_code # 200
response.json() # Parsed JSON
response.headers # Response headers
response.raise_for_status() # Raises on 4xx/5xx
# POST with JSON
payload = {"username": "alice", "password": "secret"}
response = requests.post(
"https://api.example.com/login",
json=payload,
headers={"Accept": "application/json"},
timeout=10
)
# Session (reuse connection, persist cookies)
with requests.Session() as session:
session.headers.update({"Authorization": "Bearer TOKEN"})
r = session.get("https://api.example.com/data")from flask import Flask, request, jsonify
app = Flask(__name__)
# In-memory "database"
todos = [
{"id": 1, "task": "Learn Python", "done": False},
]
@app.route("/todos", methods=["GET"])
def get_todos():
return jsonify(todos)
@app.route("/todos", methods=["POST"])
def add_todo():
data = request.get_json()
new_todo = {"id": len(todos) + 1, "task": data["task"], "done": False}
todos.append(new_todo)
return jsonify(new_todo), 201
@app.route("/todos/<int:todo_id>", methods=["DELETE"])
def delete_todo(todo_id):
global todos
todos = [t for t in todos if t["id"] != todo_id]
return jsonify({"message": "Deleted"}), 200
if __name__ == "__main__":
app.run(debug=True, port=5000)# β
Good: snake_case for variables and functions
user_name = "Alice"
def calculate_total(items):
pass
# β
Good: PascalCase for classes
class UserAccount:
pass
# β
Good: UPPER_SNAKE_CASE for constants
MAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
# β
Good: 4-space indentation
def is_even(n):
return n % 2 == 0
# β
Good: blank lines (2 around top-level, 1 inside)
class Foo:
def method_a(self):
pass
def method_b(self):
pass
# β
Good: line length β€ 79 chars; use implicit continuation
result = (
some_long_variable_name
+ another_long_variable_name
+ yet_another_variable
)# β
Use enumerate instead of range(len(...))
for i, item in enumerate(my_list):
print(i, item)
# β
Swap without temp variable
a, b = b, a
# β
Use zip for parallel iteration
for name, score in zip(names, scores):
print(f"{name}: {score}")
# β
Use any() / all()
any(x > 0 for x in numbers)
all(x > 0 for x in numbers)
# β
Use dict.get() with default
value = my_dict.get("key", "default")
# β
Use context managers
with open("file.txt") as f:
data = f.read()
# β
EAFP over LBYL (ask for forgiveness, not permission)
try:
value = my_dict["key"]
except KeyError:
value = None
# β
Use dataclasses for simple data containers
from dataclasses import dataclass, field
@dataclass
class Point:
x: float
y: float
label: str = "origin"
tags: list = field(default_factory=list)
p = Point(3.0, 4.0, "A")
print(p) # Point(x=3.0, y=4.0, label='A', tags=[])# test_math_utils.py
import pytest
def add(a, b):
return a + b
def divide(a, b):
if b == 0:
raise ZeroDivisionError
return a / b
# Test functions must start with "test_"
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
assert add(0, 0) == 0
def test_divide():
assert divide(10, 2) == 5.0
def test_divide_by_zero():
with pytest.raises(ZeroDivisionError):
divide(10, 0)
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0),
(100, 200, 300),
])
def test_add_parametrized(a, b, expected):
assert add(a, b) == expected# Run tests
pytest
pytest -v # Verbose
pytest -k "test_add" # Filter by name
pytest --tb=short # Short tracebacks# 1. pdb β Python debugger
import pdb; pdb.set_trace() # Breakpoint (legacy)
breakpoint() # Python 3.7+ shorthand
# pdb commands: n(ext), s(tep), c(ontinue), p(rint), q(uit), l(ist)
# 2. Print debugging (quick and dirty)
print(f"DEBUG: {variable = }") # Python 3.8+ f-string = trick
# 3. logging (production-grade)
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s %(levelname)s %(name)s: %(message)s"
)
logger = logging.getLogger(__name__)
logger.debug("Processing item %d", item_id)
logger.info("Request completed in %.2fs", elapsed)
logger.warning("Cache miss for key: %s", key)
logger.error("Failed to connect: %s", str(e))
logger.exception("Unhandled exception") # Includes traceback
# 4. icecream (pip install icecream)
from icecream import ic
ic(my_variable) # Pretty-prints with variable nameBEGINNER (0β3 months)
βββ Python syntax & data types
βββ Control flow (if, for, while)
βββ Functions & modules
βββ File I/O
βββ Basic OOP
INTERMEDIATE (3β6 months)
βββ Advanced OOP (inheritance, decorators)
βββ Error handling
βββ Comprehensions & generators
βββ Standard library (collections, itertools, datetime)
βββ Testing with pytest
βββ Virtual environments & pip
βββ Working with APIs (requests)
ADVANCED (6β12 months)
βββ Async programming (asyncio)
βββ Concurrency (threading, multiprocessing)
βββ Type hints & mypy
βββ Design patterns
βββ Database access (SQLAlchemy)
βββ Packaging your own library
SPECIALIZATION (choose your path)
βββ π Data Science β NumPy, Pandas, Matplotlib, Jupyter
βββ π€ ML / AI β scikit-learn, TensorFlow, PyTorch
βββ π Web Dev β Flask/FastAPI/Django
βββ βοΈ DevOps β Ansible, Boto3, Docker SDK
βββ π Security β Scapy, pwntools, cryptography
| Resource | Level | Type |
|---|---|---|
| docs.python.org | All | Official Docs |
| Automate the Boring Stuff β Al Sweigart | Beginner | Book (free online) |
| Fluent Python β Luciano Ramalho | Advanced | Book |
| Python Tricks β Dan Bader | Intermediate | Book |
| Real Python (realpython.com) | All | Tutorials |
| LeetCode / HackerRank | Intermediate+ | Practice |
| PyPI (pypi.org) | All | Package Index |
Happy coding! π The best way to learn Python is to build things you care about. Start small, be consistent, and the rest follows.