2026-03-24
python
A beginner-friendly guide to Python - covering all core topics in a clear, readable style.
This guide covers all the core topics you'll find on the official Python documentation, written in a clear, beginner-friendly style. Whether you're brand new to Python or brushing up, use it as a quick reference before diving into projects.
1. Introduction
- What is Python? A high-level, interpreted, dynamically typed language created by Guido van Rossum (1991). It emphasizes readability and simplicity — Python code often reads almost like plain English.
- Why learn Python?
- Clean, minimal syntax → fast to write and easy to read.
- Massive ecosystem: data science, web, automation, AI/ML.
- Batteries included — rich standard library out of the box, so you can do a lot without installing anything extra.
- How to run Python?
- Install Python from python.org
- Install VSCodium from vscodium.com
- Then you can create a new file called
hello.py - Or try it instantly in your browser at python.org/shell.
2. Program Structure
After creating a new file called hello.py with the following contents:
# hello.py
def main():
print("Hello, Python!")
if __name__ == "__main__":
main() You can then run it in the terminal! With the following effects:
print()outputs text to the screen — it's your best friend when learning!def main():defines a function (a reusable block of code). More on functions in section 13.- The
if __name__ == "__main__"line is a safety guard. It means: "only runmain()if this file is being run directly, not if it's being imported by another file." Don't worry too much about this for now — just know it's a good habit. - Indentation (4 spaces) defines blocks — Python uses whitespace instead of
{ }braces. - Each
.pyfile is called a module, and you can import code from one file into another.
3. Syntax Basics
| Element | Example | Notes |
|---|---|---|
| Comments | # this is a comment | Single-line; starts with #. Ignored by Python — just for humans. |
| Docstrings | """triple quoted""" | Multi-line strings used to document functions and classes. |
| Identifiers | my_var, _private | Variable names use snake_case by convention; case-sensitive (age ≠ Age). |
| Newline | (end of line) | Ends a statement. Unlike many languages, no semicolons needed. |
4. Variables & Data Types
A variable is just a named container for a value. In Python, you don't need to declare a type — Python figures it out automatically.
age = 25 # int
price = 9.99 # float
name = "Alice" # str
is_happy = True # bool
nothing = None # NoneType "Mutable" vs "immutable" — mutable means you can change it after creating it; immutable means you can't.
| Type | Example | Notes |
|---|---|---|
int | 42, -7, 0xFF | Whole numbers. Python handles numbers of any size. |
float | 3.14, 1e-3 | Decimal numbers (1e-3 means 0.001). |
complex | 3 + 4j | Numbers with a real and imaginary part. Rarely needed as a beginner. |
bool | True, False | Either true or false. Note the capital letters! |
str | "hello", 'world' | Text. Immutable — you can't change individual characters. |
bytes | b"data" | Raw binary data. You'll encounter this when dealing with files or networking. |
list | [1, 2, 3] | An ordered collection. Mutable — you can add, remove, or change items. |
tuple | (1, 2, 3) | Like a list, but immutable. Good for data that shouldn't change. |
set | {1, 2, 3} | An unordered collection with no duplicates. Mutable. |
dict | {"a": 1} | Key-value pairs (like a real dictionary: word → definition). Mutable. |
NoneType | None | Represents "nothing" or the absence of a value. Like null in other languages. |
Tip: Use
type(x)to check what type a variable is. For example,type(42)returns<class 'int'>. Useisinstance(x, int)to check ifxis an integer.
5. Operators
| Category | Symbols | Example |
|---|---|---|
| Arithmetic | + - * / // % ** | 7 // 2 → 3, 2 ** 8 → 256 |
| Assignment | = += -= *= /= //= %= **= | x += 1 is shorthand for x = x + 1 |
| Comparison | == != < > <= >= | a == b (note: two equals signs to compare, one to assign) |
| Identity | is is not | x is None (checks if two variables point to the same object) |
| Membership | in not in | "a" in "cat" → True |
| Logical | and or not | x > 0 and x < 10 |
| Bitwise | & | ^ ~ << >> | mask & 0xFF (manipulates individual bits — advanced topic) |
Note:
/always returns a float (e.g.,4 / 2→2.0).//is integer (floor) division — it rounds down. So5 // 2→2, not2.5.%is the modulo operator: it gives you the remainder (7 % 3→1).
6. Booleans
A boolean is simply True or False. It's the foundation of all decision-making in code.
flag = True
if flag:
print("yes")
else:
print("no") - Falsy values are things Python treats as
Falsein a condition:False,None,0,0.0,""(empty string),[](empty list),{}(empty dict),set()(empty set). - Everything else is truthy (treated as
True). and/oruse short-circuit evaluation: Python stops evaluating as soon as the result is certain. For example,False and <anything>immediately returnsFalsewithout checking the second part.
7. Conditional Statements
Conditionals let your program make decisions.
if / elif / else
if score >= 90:
print("A")
elif score >= 80:
print("B")
else:
print("C or below") - Python checks each condition from top to bottom and runs the first block that matches.
elifis short for "else if". You can have as manyelifblocks as you need.- Ternary expression (a one-liner if/else):
grade = "pass" if score >= 60 else "fail"
match (Python 3.10+)
match command:
case "quit":
quit()
case "go" | "move":
move()
case _: # _ is a wildcard — matches anything
print("unknown command") - Think of
matchas a cleaner way to write manyif/elifchecks against the same variable. - Structural pattern matching — more powerful than a simple
switchin other languages.
8. Loops
Loops repeat a block of code. There are two kinds:
| Loop | Syntax | When to use |
|---|---|---|
| while | while cond: | Repeat as long as a condition is true. |
| for | for x in iterable: | Repeat once for each item in a collection. |
# Print numbers 1 through 5
for i in range(1, 6):
print(i)
# Count down from 10 to 1
n = 10
while n > 0:
n -= 1 Tip:
range(start, stop)generates numbers fromstartup to (but not including)stop. Sorange(1, 6)gives1, 2, 3, 4, 5.
break— exit the loop immediately, even if the condition is still true.continue— skip the rest of this iteration and jump to the next one.elseclause on a loop runs when the loop finishes normally (i.e., nobreakwas hit).
9. Lists & Tuples
A list is an ordered, changeable collection of items. Items can be of any type.
nums = [1, 2, 3, 4, 5]
first = nums[0] # 1 — indexing starts at 0!
last = nums[-1] # 5 — negative index counts from the end
sub = nums[1:3] # [2, 3] — slicing: from index 1 up to (not including) 3 - List comprehension — a compact way to build a list:
[x * 2 for x in nums if x > 2]→[6, 8, 10] - Tuples:
point = (3, 4)— immutable lists. Use them for data that shouldn't change, like coordinates. Unpack withx, y = point.
# Common list operations
nums.append(6) # add one item to the end
nums.extend([7, 8]) # add multiple items to the end
nums.sort() # sort in place (modifies the list)
doubled = list(map(lambda x: x * 2, nums)) # double every item
evens = list(filter(lambda x: x % 2 == 0, nums)) # keep only even items
total = sum(nums) # add everything up 10. Dictionaries & Sets
A dictionary (dict) stores key-value pairs — like a lookup table or a real dictionary (word → definition).
person = {"name": "Alice", "age": 30}
person["city"] = "NYC" # add a new key
age = person.get("age", 0) # safe access: returns 0 if "age" doesn't exist
# Loop over all key-value pairs
for key, val in person.items():
print(key, val) # Dict comprehension — build a dict in one line
squares = {x: x**2 for x in range(1, 6)}
# → {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Sets — unordered collections with no duplicates
a = {1, 2, 3}
b = {2, 3, 4}
print(a | b) # union (all items from both) → {1, 2, 3, 4}
print(a & b) # intersection (items in both) → {2, 3}
print(a - b) # difference (in a but not in b) → {1} 11. Strings
Strings are sequences of characters. They're immutable — you can't change a character in place, but you can create new strings from operations.
s = "Hello, World!"
print(len(s)) # 13 — number of characters
print(s.upper()) # "HELLO, WORLD!"
print(s.replace("World", "Python")) # "Hello, Python!"
print(s.split(", ")) # ["Hello", "World!"] — splits on ", "
print(s[0:5]) # "Hello" — slicing works like lists - f-strings (Python 3.6+): the easiest way to embed variables in a string:
f"Name: {name}, Age: {age}". Thefprefix tells Python to evaluate the{}expressions. - Multi-line strings: wrap in
"""..."""or'''...'''.
12. User Input
name = input("Enter your name: ")
age = int(input("Enter your age: ")) # convert the string to an integer
print(f"Hello, {name}! You are {age} years old.") input()always returns a string, even if the user types a number. You need to explicitly convert it:int("42")→42,float("3.14")→3.14.
13. Functions
A function is a reusable block of code. Instead of copy-pasting the same logic, you define it once and call it whenever you need it.
Definition
def add(a, b):
return a + b
result = add(3, 5) # result = 8 Default & Keyword Arguments
def greet(name, greeting="Hello"): # "Hello" is the default if no greeting is given
print(f"{greeting}, {name}!")
greet("Alice") # Hello, Alice!
greet("Bob", greeting="Hi") # Hi, Bob! — passing by keyword name *args and **kwargs
These let a function accept any number of arguments:
def variadic(*args, **kwargs):
print(args) # a tuple of all positional arguments: (1, 2, 3)
print(kwargs) # a dict of all keyword arguments: {"color": "red"}
variadic(1, 2, 3, color="red") *argscatches extra positional arguments (passed by position).**kwargscatches extra keyword arguments (passed by name).
Lambda Functions
A lambda is a short, anonymous (unnamed) function written in one line. Best for simple operations:
square = lambda x: x ** 2
result = square(5) # 25
# Often used with map/filter/sort:
nums = [3, 1, 4, 1, 5]
nums.sort(key=lambda x: -x) # sort in descending order Scope (where variables live)
| Scope | Notes |
|---|---|
| Local | Variables created inside a function. They disappear when the function returns. |
| Enclosing | Variables from an outer function, accessible in nested (inner) functions. Use nonlocal to modify them. |
| Global | Variables defined at the top of a file. Use global inside a function to modify them. |
| Built-in | Python's built-in names like len, print, range. Always available. |
14. Comprehensions
Comprehensions are a concise, Pythonic way to build collections. Think of them as a one-line for loop that produces a value.
# List comprehension — [expression for item in iterable if condition]
squares = [x**2 for x in range(10)]
# same as: squares = []; for x in range(10): squares.append(x**2)
# Dict comprehension
inverted = {v: k for k, v in mapping.items()}
# Set comprehension
unique_lens = {len(w) for w in words}
# Generator expression (lazy — computes values on demand, uses less memory)
total = sum(x**2 for x in range(1_000_000)) Tip: If the result is just going to be consumed once (like in
sum()), use a generator expression (no square brackets). If you need to store and reuse the list, use a list comprehension.
15. Iterators & Generators
A generator is a function that produces a sequence of values one at a time, instead of building the whole list in memory at once. It uses the yield keyword.
def countdown(n):
while n > 0:
yield n # pause here, send n to the caller, then resume next time
n -= 1
for num in countdown(5):
print(num) # prints 5, 4, 3, 2, 1 - Think of
yieldlike a pause button: the function pauses, hands a value to the caller, then resumes from that exact point next time. - Generators are memory-efficient — great for processing large files or infinite sequences.
- Use
next(gen)to manually get the next value from a generator or iterator.
16. Classes & Objects
A class is a blueprint for creating objects. An object is an instance of a class — for example, alice is an object (instance) of the Person class.
class Person:
species = "Homo sapiens" # class attribute — shared by ALL Person objects
def __init__(self, name, age):
# __init__ runs automatically when you create a new Person
self.name = name # instance attribute — unique to each object
self.age = age
def greet(self):
# self refers to the specific object calling this method
return f"Hi, I'm {self.name}."
def __repr__(self):
# How this object looks when printed or inspected
return f"Person({self.name!r}, {self.age})"
alice = Person("Alice", 30) # create a Person object
print(alice.greet()) # Hi, I'm Alice. Inheritance
Inheritance lets one class reuse and extend another class's code:
class Employee(Person): # Employee inherits from Person
def __init__(self, name, age, role):
super().__init__(name, age) # call Person's __init__ to set name & age
self.role = role
def greet(self):
# Override Person's greet method
return f"{super().greet()} I work as {self.role}." - Python supports multiple inheritance (inheriting from more than one class). The order Python uses to look up methods is called the MRO (Method Resolution Order).
- Dunder methods (double underscore, like
__init__,__repr__,__len__) are special methods that customize how your objects behave with built-in Python operations.
17. Error Handling
Errors in Python are called exceptions. Instead of crashing, you can catch them and handle them gracefully.
try:
result = int(input("Enter a number: "))
except ValueError as e:
# Runs if the user types something that isn't a number
print(f"Bad input: {e}")
except (TypeError, ZeroDivisionError):
# You can catch multiple exception types in one line
print("Type or division error")
else:
# Runs only if NO exception was raised
print(f"Got {result}")
finally:
# ALWAYS runs, whether an exception happened or not — great for cleanup
print("Done") raise ValueError("msg")— throw an exception yourself (e.g., to signal bad input).raisealone — re-raises the current exception (pass it up the call stack).- Define custom exceptions by subclassing
Exception:class MyError(Exception): pass.
| Technique | Description |
|---|---|
try/except | Catch specific or broad exceptions. |
else clause | Runs when no exception was raised in the try block. |
finally clause | Cleanup that always executes (close files, release locks, etc.). |
Context managers (with) | Automatic resource management — see section 18. |
18. Context Managers
A context manager (used with with) automatically handles setup and cleanup for you — like ensuring a file is closed even if an error occurs.
with open("data.txt", "r") as f:
content = f.read()
# The file is automatically closed here, no matter what - Without
with, you'd need to manually callf.close()and worry about doing it in error cases. - Under the hood,
withcalls__enter__when entering the block and__exit__when leaving (even on exception). - You can create your own context managers using
contextlib.contextmanageror by adding__enter__/__exit__methods to a class.
19. File I/O
| Mode | Meaning |
|---|---|
"r" | Read (text, default). Fails if the file doesn't exist. |
"w" | Write (overwrites / creates the file). |
"a" | Append (adds to the end without erasing). |
"rb" / "wb" | Binary read / write (for images, PDFs, etc.). |
# Write to a file
with open("out.txt", "w") as f:
f.write("Hello\n")
# Read line by line (memory-efficient for large files)
with open("out.txt") as f:
for line in f:
print(line.strip()) # .strip() removes the trailing newline
# Read the whole file into a string at once
with open("out.txt") as f:
text = f.read() 20. Modules & Packages
A module is any .py file. A package is a folder of modules with an __init__.py file. You import code to reuse it:
import math
from os import path, getcwd
from collections import defaultdict, Counter
import json
print(math.sqrt(16)) # 4.0
data = json.loads('{"a": 1}') # parse JSON string into a Python dict - Use
pip install <package>to install third-party packages (e.g.,pip install requests). - Virtual environments keep each project's dependencies separate:
python -m venv .venvcreates one, then activate it withsource .venv/bin/activate(Mac/Linux) or.venv\Scripts\activate(Windows).
21. Decorators
A decorator wraps a function to add extra behavior before or after it runs — without changing the function's code. The @decorator_name syntax is just shorthand for my_func = decorator(my_func).
import functools
def timer(func):
@functools.wraps(func) # preserves the original function's name & docstring
def wrapper(*args, **kwargs):
import time
t0 = time.perf_counter()
result = func(*args, **kwargs) # call the original function
print(f"{func.__name__} took {time.perf_counter()-t0:.4f}s")
return result
return wrapper
@timer # this is equivalent to: slow = timer(slow)
def slow():
import time; time.sleep(0.1)
slow() # prints: slow took 0.1001s - Common built-in decorators you'll use often:
@staticmethod— a method that doesn't needself(doesn't access the object).@classmethod— a method that receives the class itself as the first argument.@property— makes a method behave like an attribute.
22. Core Standard Library Highlights
Python comes with a huge library of useful modules. Here are the most commonly used:
| Module | Key Uses | Example |
|---|---|---|
os | File system, env vars | os.listdir(".") |
sys | Interpreter info, command-line args | sys.argv[1] |
pathlib | Object-oriented file paths | Path("data") / "file.txt" |
json | JSON encode/decode | json.dumps({"a": 1}) |
re | Regular expressions (pattern matching) | re.findall(r"\d+", text) |
datetime | Dates and times | datetime.now() |
collections | Useful data structures | Counter("abracadabra") |
itertools | Efficient looping tools | itertools.chain(a, b) |
functools | Function utilities | @functools.lru_cache (caching) |
threading | Run code in parallel threads | threading.Thread(target=f) |
asyncio | Async I/O (non-blocking code) | asyncio.run(main()) |
subprocess | Run shell commands from Python | subprocess.run(["ls"]) |
dataclasses | Auto-generate class boilerplate | @dataclass |
23. Quick Reference Cheat Sheet
# Variables with type hints (optional but helpful)
x: int = 42
name: str = "Alice"
items: list[int] = [1, 2, 3]
# Comprehensions
squares = [n**2 for n in range(1, 6)]
evens = {n for n in range(10) if n % 2 == 0}
# Function with type hints
def greet(name: str, times: int = 1) -> str:
return (f"Hello, {name}!\n") * times
# Class
class Point:
def __init__(self, x: float, y: float):
self.x, self.y = x, y
def distance(self) -> float:
return (self.x**2 + self.y**2) ** 0.5
# Error handling
try:
val = int("abc")
except ValueError:
val = 0
# File I/O
with open("data.txt", "w") as f:
f.write("hello\n")
# Generator (infinite sequence)
def fib():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Async (for I/O-bound tasks like web requests)
import asyncio
async def fetch(url: str) -> str:
await asyncio.sleep(1) # simulate waiting for a network response
return url
asyncio.run(fetch("https://example.com")) Final Note
This guide covers all the fundamentals you need to start writing real Python programs. If something didn't click the first time — that's totally normal! The best way to learn is to write code, break things, and look things up.
When you're ready to go deeper, check out:
- docs.python.org — the official Python documentation
- python.org/about/gettingstarted — the official beginner's guide
- Automate the Boring Stuff with Python by Al Sweigart — free online, very practical
- Fluent Python by Luciano Ramalho — excellent once you know the basics
Happy coding!