Python Tutorial
Python is an easy-to-learn, general-purpose programming language used for web development, data science, AI, automation, scripting, and more. It prioritizes readability with its clean, indentation-based syntax.
What is Python?
- Created by Guido van Rossum, released in 1991.
- Current version: Python 3.x (Python 2 is end-of-life).
- Interpreted, dynamically typed, multi-paradigm.
- Popular for: web (Django, Flask, FastAPI), ML/AI (TensorFlow, PyTorch, scikit-learn), automation, scripting.
Python
# Hello World - Python
print("Hello, World!")
# Run script
# python3 hello.py
# Python version
import sys
print(sys.version)
Syntax & Comments
Python
# This is a single-line comment
"""
This is a
multi-line docstring (triple quotes)
"""
# Python uses INDENTATION (4 spaces) for blocks - no braces {}
if True:
print("Indented block")
if True:
print("Nested block")
# Semicolons are optional (not recommended)
a = 1; b = 2
# Line continuation
total = 1 + 2 + 3 + \
4 + 5
# Multiple assignment
x, y, z = 1, 2, 3
a = b = c = 0
Variables
Python
# No declaration keyword needed
name = "Alice"
age = 25
height = 5.9
is_admin = True
# Dynamic typing
x = 10
x = "now a string" # OK in Python
# Type hints (optional, Python 3.5+)
def greet(name: str) -> str:
return f"Hello, {name}"
# Check type
type(name) # <class 'str'>
type(age) # <class 'int'>
isinstance(age, int) # True
# Constants (convention: UPPER_CASE - not enforced)
MAX_SIZE = 100
PI = 3.14159
# Delete variable
del x
Data Types
| Type | Example | Mutable? |
|---|---|---|
| int | 42, -7, 0 | No |
| float | 3.14, -0.5, 2e10 | No |
| complex | 3+4j | No |
| str | "hello", 'world' | No |
| bool | True, False | No |
| list | [1, 2, 3] | Yes |
| tuple | (1, 2, 3) | No |
| set | {1, 2, 3} | Yes |
| dict | {"key": "value"} | Yes |
| None | None | - |
| bytes | b"hello" | No |
Python
# Type conversion
int("42") # 42
float("3.14") # 3.14
str(42) # "42"
bool(0) # False
list("abc") # ['a', 'b', 'c']
tuple([1, 2]) # (1, 2)
set([1, 1, 2]) # {1, 2}
Strings
Python
s = "Hello, World!"
len(s) # 13
s.upper() # "HELLO, WORLD!"
s.lower() # "hello, world!"
s.title() # "Hello, World!"
s.strip() # remove whitespace
s.lstrip(" ") # left strip
s.rstrip("!") # right strip
s.replace("World", "Python") # "Hello, Python!"
s.split(", ") # ['Hello', 'World!']
", ".join(["a","b","c"]) # "a, b, c"
s.find("World") # 7
s.startswith("He") # True
s.endswith("!") # True
s.count("l") # 3
s.isdigit() # False
s.isalpha() # False
s.isalnum() # False
# Slicing: s[start:stop:step]
s[0:5] # "Hello"
s[-6:] # "orld!"
s[::-1] # reverse: "!dlroW ,olleH"
s[::2] # every 2nd char
# f-strings (Python 3.6+) - preferred
name, age = "Alice", 25
msg = f"Name: {name}, Age: {age}, Born: {2025 - age}"
msg = f"Pi: {3.14159:.2f}" # format specifier
# Other string formatting
"Hello, {}!".format("World")
"Hello, %s!" % "World"
# Raw string (no escape processing)
path = r"C:\Users\name\file.txt"
# Multi-line
text = """
Line 1
Line 2
"""
Lists
Python
fruits = ["apple", "banana", "cherry"]
# Access
fruits[0] # "apple"
fruits[-1] # "cherry"
fruits[1:3] # ["banana", "cherry"]
# Modify
fruits.append("date") # add to end
fruits.insert(1, "avocado") # insert at index
fruits.extend(["elderberry", "fig"])
fruits.remove("banana") # remove by value
fruits.pop() # remove and return last
fruits.pop(1) # remove at index
fruits.clear() # empty list
# Searching
"apple" in fruits # True
fruits.index("cherry") # 2
fruits.count("apple") # 1
# Sorting
fruits.sort() # in-place (ascending)
fruits.sort(reverse=True) # descending
fruits.sort(key=len) # by string length
sorted_copy = sorted(fruits) # returns new list
fruits.reverse()
# Copy
copy = fruits.copy() # shallow copy
copy = fruits[:] # slice copy
# List operations
[1, 2] + [3, 4] # [1, 2, 3, 4]
[0] * 5 # [0, 0, 0, 0, 0]
len(fruits) # length
min([1,3,2]) # 1
max([1,3,2]) # 3
sum([1,2,3]) # 6
list(range(5)) # [0, 1, 2, 3, 4]
list(range(1, 6, 2)) # [1, 3, 5]
# Unpacking
a, b, *rest = [1, 2, 3, 4, 5]
# a=1, b=2, rest=[3,4,5]
Dictionaries
Python
person = {
"name": "Alice",
"age": 25,
"hobbies": ["coding", "reading"]
}
# Access
person["name"] # "Alice"
person.get("email") # None (no error)
person.get("email", "N/A") # "N/A" default
# Modify
person["age"] = 26
person["email"] = "alice@example.com"
del person["age"]
person.pop("age") # remove and return
# Check key
"name" in person # True
# Iterate
for key in person: print(key)
for key, val in person.items(): print(key, val)
for key in person.keys(): print(key)
for val in person.values(): print(val)
# Merge (Python 3.9+)
merged = person | {"role": "admin"}
# Dictionary methods
person.keys() # dict_keys([...])
person.values() # dict_values([...])
person.items() # dict_items([(...)])
person.update({"age": 26, "city": "Mumbai"})
person.setdefault("country", "India") # add if missing
# Dict comprehension
squares = {n: n**2 for n in range(1, 6)}
# {1:1, 2:4, 3:9, 4:16, 5:25}
Functions
Python
def greet(name, greeting="Hello"):
"""Greet a person by name."""
return f"{greeting}, {name}!"
greet("Alice") # "Hello, Alice!"
greet("Bob", "Hi") # "Hi, Bob!"
greet(name="Carol", greeting="Hey") # keyword args
# *args (variable positional args)
def add(*nums):
return sum(nums)
add(1, 2, 3, 4) # 10
# **kwargs (variable keyword args)
def info(**kwargs):
for key, val in kwargs.items():
print(f"{key}: {val}")
info(name="Alice", age=25)
# Combined
def func(pos, *args, keyword=True, **kwargs):
pass
# Return multiple values
def minmax(lst):
return min(lst), max(lst)
lo, hi = minmax([3, 1, 4, 1, 5])
# First-class functions
def apply(func, value):
return func(value)
apply(str.upper, "hello") # "HELLO"
Comprehensions
Python
# List comprehension
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
words = [w.upper() for w in ["hello", "world"]]
# Nested
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
# Dict comprehension
inv = {v: k for k, v in {"a": 1, "b": 2}.items()}
# Set comprehension
unique_lengths = {len(w) for w in ["hi", "hello", "hey"]}
# Generator expression (lazy evaluation - memory efficient)
gen = (x**2 for x in range(1000000))
next(gen) # 0
sum(x for x in range(100)) # 4950
Classes & OOP
Python
class Animal:
# Class variable (shared)
kingdom = "Animalia"
def __init__(self, name, sound):
self.name = name # instance variable
self.sound = sound
def speak(self):
return f"{self.name} says {self.sound}"
def __repr__(self):
return f"Animal(name={self.name!r})"
@classmethod
def from_dict(cls, data):
return cls(data["name"], data["sound"])
@staticmethod
def breathes(): return True
class Dog(Animal): # inheritance
def __init__(self, name, breed):
super().__init__(name, "Woof")
self.breed = breed
def speak(self): # override
return super().speak() + " *wags tail*"
def fetch(self):
return f"{self.name} fetches the ball!"
rex = Dog("Rex", "Labrador")
rex.speak() # "Rex says Woof *wags tail*"
isinstance(rex, Dog) # True
isinstance(rex, Animal) # True
# Dunder (magic) methods
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, o): return Vector(self.x+o.x, self.y+o.y)
def __str__(self): return f"({self.x}, {self.y})"
def __len__(self): return 2
def __eq__(self, o): return self.x==o.x and self.y==o.y
Exception Handling
Python
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero!")
except (TypeError, ValueError) as e:
print(f"Type or value error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
else:
print("No exception occurred") # runs if no exception
finally:
print("Always runs (cleanup)") # always runs
# Raise exceptions
def validate_age(age):
if not isinstance(age, int):
raise TypeError("Age must be an integer")
if age < 0 or age > 150:
raise ValueError(f"Invalid age: {age}")
return age
# Custom exception
class DatabaseError(Exception):
def __init__(self, message, code=None):
super().__init__(message)
self.code = code
raise DatabaseError("Connection failed", code=503)
# Context managers (with statement)
with open("file.txt", "r") as f:
content = f.read()
# file automatically closed after block
File I/O
Python
# Read file
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read() # entire file as string
# or
lines = f.readlines() # list of lines
# or
for line in f: # iterate line by line
print(line.strip())
# Write file (overwrites)
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, File!\n")
f.writelines(["line1\n", "line2\n"])
# Append to file
with open("log.txt", "a") as f:
f.write("New log entry\n")
# JSON
import json
data = {"name": "Alice", "age": 25}
# Write JSON
with open("data.json", "w") as f:
json.dump(data, f, indent=2)
# Read JSON
with open("data.json") as f:
loaded = json.load(f)
# JSON string
json_str = json.dumps(data, indent=2)
parsed = json.loads(json_str)
# CSV
import csv
with open("data.csv", "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["name","age"])
writer.writeheader()
writer.writerow({"name": "Alice", "age": 25})
Tip: Use
pathlib.Path for modern file path handling: from pathlib import Path; p = Path("folder") / "file.txt"Virtual Environments
A virtual environment isolates project packages so one project can use different dependencies from another.
Terminal
python -m venv .venv
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS / Linux
source .venv/bin/activate
python -m pip install requests pytest
python -m pip freeze > requirements.txt
Type Hints
Python stays dynamic at runtime, but type hints make your code easier to read, test, and analyze with tools.
Python
from typing import Iterable
def average(values: Iterable[float]) -> float:
values = list(values)
if not values:
raise ValueError("values cannot be empty")
return sum(values) / len(values)
user: dict[str, str] = {"name": "Aisha", "role": "student"}
Testing
Automated tests catch regressions and prove your functions behave as expected. Start with small units and clear assertions.
Python + pytest
def add(a: int, b: int) -> int:
return a + b
def test_add() -> None:
assert add(2, 3) == 5
assert add(-1, 1) == 0