Python Syntax Notes
Core Python only. Every syntax: topic name, one line, then the code.
Basics
Comments
Notes ignored by Python.
# single line """multi-line string, also used as docstring"""
Variables
Names bound to values; no type declaration needed.
x = 10 name = "Ann"
Multiple assignment & swap
Assign several names at once or swap values.
a, b = 1, 2 a = b = 0 a, b = b, a
Unpacking
Split a sequence into names; * collects the rest.
first, *rest = [1, 2, 3] *init, last = [1, 2, 3]
Indentation
Blocks are defined by 4-space indentation, not braces.
if True:
print("inside block")
Line continuation
Split long lines with a backslash or brackets.
total = 1 + 2 + \
3
items = [1,
2]
a = 1; b = 2 # two statements on one lineData types
Numbers
Integers, floats and complex numbers.
42 0b101 0o17 0xFF 1_000_000
3.14 1e-3 float("inf")
3 + 4j
Bool and None
Truth values and the "nothing" value.
True False None
Type check
Find or test an object's type.
type(x) isinstance(x, int) isinstance(x, (int, float))
Type conversion
Convert between types with constructors.
int("5") float("1.5") str(5) bool(0)
list("ab") tuple([1]) set([1])
chr(65) ord("A") hex(255) bin(5) oct(8)Operators
Arithmetic
/ always gives float; // floors.
+ - * / // % **
Comparison
Compare values; chaining is allowed.
== != < > <= >= 1 < x < 10
Logical
Combine conditions with words, not symbols.
and or not
Identity & membership
Same object? Item inside a collection?
x is None x is not None 3 in [1, 2, 3] 3 not in L
Bitwise
Operate on the bits of integers.
& | ^ ~ << >>
Augmented assignment
Update a variable in place.
x += 1 x -= 1 x *= 2 x /= 2 x //= 2 x %= 2 x **= 2
Conditional expression
One-line if/else that returns a value.
y = a if cond else b v = x or "default"
Strings
Indexing & slicing
Access characters by position; negative counts from the end.
s = "hello" s[0] s[-1] s[1:3] s[::2] s[::-1] s + "x" s * 3 "e" in s len(s)
f-strings
Embed expressions and format them inline.
f"{name}" f"{x:.2f}" f"{x:>10}" f"{n:,}" f"{x!r}" f"{x=}"
"{} {}".format(1, 2)
"%s %d" % ("a", 1)
Escapes & raw strings
Special characters inside strings.
\n \t \\ \' \" \xhh \uXXXX r"raw\n" b"bytes"
String methods
Built-in tools to transform and test text.
s.upper() s.lower() s.title() s.strip() s.split(",") ",".join(L)
s.replace("a","b") s.find("x") s.count("a") s.startswith("h") s.endswith("o")
s.isalpha() s.isdigit() s.isalnum() s.center(10) s.zfill(5) s.splitlines()Collections
List
Ordered, changeable sequence.
l = [1, 2, 3] l[0] l[1:] l.append(4) l.extend([5]) l.insert(0, 0) l.remove(2) l.pop() l.index(3) l.count(1) l.sort() l.reverse() del l[0]
Tuple
Ordered, unchangeable sequence.
t = (1, 2) t = 1, t = ()
Set
Unordered collection of unique items.
s = {1, 2} s.add(3) s.discard(1)
a | b a & b a - b a ^ b
Dictionary
Key-value pairs.
d = {"a": 1, "b": 2}
d["a"] d["c"] = 3 del d["a"] "a" in d
d.get("x", 0) d.keys() d.values() d.items() d.update(o) d.pop("a")Control flow
if / elif / else
Run code only when a condition is true.
if x > 0:
...
elif x == 0:
...
else:
...
for loop
Repeat over any iterable.
for i in range(5): ... for i, v in enumerate(L): ... for a, b in zip(A, B): ... for k, v in d.items(): ...
while loop
Repeat while a condition holds.
while cond:
...
break, continue, else, pass
Control the loop; else runs if no break happened.
for x in L:
if a: continue
if b: break
else:
...
pass # do nothingFunctions
Define & call
Reusable block of code that can return a value.
def add(a, b=2):
"""docstring"""
return a + b
add(1) add(1, b=5)
Return multiple values
Return a tuple and unpack it.
def pair(): return 1, 2 x, y = pair()
Lambda
Small anonymous function.
square = lambda n: n * n
Input, output & files
print and input
Show output and read user text.
print("a", "b", sep="-", end="")
name = input("Name: ")
Reading & writing files
with closes the file for you. Modes: r w a x b +.
with open("f.txt", "r", encoding="utf-8") as f:
data = f.read() # readline() readlines()
with open("f.txt", "w") as f:
f.write("text")Exceptions (basic)
try / except / else / finally
Handle runtime errors gracefully.
try:
x = int("a")
except ValueError as e:
print(e)
else:
... # no error
finally:
... # always runs
raise & assert
Trigger an error yourself or check an assumption.
raise ValueError("bad")
assert x > 0, "must be positive"Comprehensions
List, set, dict, generator
Build collections in one readable line.
[x * 2 for x in range(5) if x % 2]
{x for x in "hello"}
{k: v for k, v in d.items()}
(x * x for x in range(5))
[(a, b) for a in A for b in B]Functions in depth
*args and **kwargs
Accept any number of positional or keyword arguments.
def f(a, b=2, *args, c, d=4, **kwargs): ...
f(*[1, 2], **{"c": 3})
Positional-only and keyword-only
/ and * restrict how arguments are passed.
def g(a, b, /, c, *, d): ...
Scope: global & nonlocal
Modify variables from an outer scope.
counter = 0
def inc():
global counter
counter += 1
def outer():
n = 0
def inner():
nonlocal n
n += 1
return inner
Functional built-ins
Process iterables without explicit loops.
map(f, L) filter(f, L) sorted(L, key=lambda x: x[1], reverse=True) any(L) all(L) min(L, key=len) sum(L) zip(A, B, strict=True)
OOP: classes
Class & object
A class is a blueprint; __init__ sets up each object.
class Animal:
count = 0 # class attribute
def __init__(self, name):
self.name = name # instance attribute
self._prot = 1 # protected by convention
self.__priv = 2 # name-mangled
def speak(self):
return f"{self.name} makes a sound"
a = Animal("Rex")
a.name a.speak() Animal.count
Class & static methods
Methods that belong to the class, not the instance.
@classmethod
def create(cls, name): return cls(name)
@staticmethod
def helper(x): return x * 2
Properties
Getter/setter behaviour behind attribute syntax.
@property
def upper(self): return self.name.upper()
@upper.setter
def upper(self, v): self.name = v.lower()
String representation
Control how objects print.
def __repr__(self): return f"Animal({self.name!r})"
def __str__(self): return self.name
Attribute helpers
Inspect and change objects dynamically.
hasattr(a, "x") getattr(a, "x", None) setattr(a, "x", 1) delattr(a, "x") vars(a) dir(a) type(a) a.__class__.__name__
OOP: inheritance & polymorphism
Inheritance
A child class reuses and overrides parent behaviour.
class Dog(Animal):
def __init__(self, name):
super().__init__(name)
def speak(self): # override
return f"{self.name} barks"
Multiple inheritance & MRO
Inherit from several classes; MRO decides lookup order.
class Bird(Animal, Flyer): ... Bird.__mro__
isinstance & issubclass
Check relationships between objects and classes.
isinstance(d, Animal) issubclass(Dog, Animal)
Abstract classes
Force subclasses to implement certain methods.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self): ...Dataclasses & enums
dataclass
Auto-generates __init__, __repr__, __eq__.
from dataclasses import dataclass, field
@dataclass(frozen=True, order=True, slots=True)
class Point:
x: int
y: int = 0
tags: list = field(default_factory=list)
Enum
A fixed set of named constants.
from enum import Enum, auto
class Color(Enum):
RED = auto()
BLUE = 2
Color.RED.name Color.RED.value Color(2)Modules & packages
import
Reuse code from other files and libraries.
import math import math as m from math import sqrt, pi from math import sqrt as s from . import sibling from .pkg import name
Main guard & __all__
Run code only when executed directly; control public names.
__all__ = ["public_name"]
if __name__ == "__main__":
main()Exceptions (custom & chaining)
Custom exception
Subclass Exception for your own errors.
class AppError(Exception):
def __init__(self, msg, code):
super().__init__(msg)
self.code = code
Chaining & re-raise
Keep the original cause or hide it.
except (TypeError, KeyError) as e:
raise AppError("failed", 1) from e
except Exception:
raise
raise ValueError("x") from NoneIterators & generators
Iterator protocol
Any object with __iter__ and __next__.
class Count:
def __init__(self, n): self.n, self.i = n, 0
def __iter__(self): return self
def __next__(self):
if self.i >= self.n: raise StopIteration
self.i += 1
return self.i
it = iter(L) next(it) next(it, None)
Generator function
yield produces values lazily, one at a time.
def gen():
yield 1
yield 2
yield from other()Context managers
with statement
Guarantees setup and cleanup around a block.
with open("a") as a, open("b") as b: ...
with (open("a") as a, open("b") as b): ... # 3.10+
Custom context manager
Implement __enter__ and __exit__.
class Ctx:
def __enter__(self): return self
def __exit__(self, exc_type, exc, tb): return FalseDecorators
Function decorator
Wrap a function to add behaviour.
def deco(fn):
def wrapper(*args, **kwargs):
return fn(*args, **kwargs)
return wrapper
@deco
def work(): ...
Decorator with arguments
A factory that returns a decorator.
def repeat(n):
def d(fn):
def w(*a, **k):
for _ in range(n): fn(*a, **k)
return w
return d
@repeat(3)
def hi(): ...match / case
Structural pattern matching (3.10+)
Match values and shapes of data.
match command:
case "go": ...
case "stop" | "halt": ...
case [x, y]: ...
case [first, *rest]: ...
case {"type": "a", "v": v}: ...
case Point(x=0, y=0): ...
case int() | float() as n if n > 0: ...
case _: ...Dunder (magic) methods
Operator overloading
Make your objects work with operators and built-ins.
class Vec:
def __init__(self, x, y): self.x, self.y = x, y
def __add__(self, o): return Vec(self.x + o.x, self.y + o.y)
def __eq__(self, o): return (self.x, self.y) == (o.x, o.y)
def __hash__(self): return hash((self.x, self.y))
def __len__(self): return 2
def __getitem__(self, i): return (self.x, self.y)[i]
def __call__(self): return "called"
Full list
Special names Python calls for you.
__new__ __init__ __del__ __repr__ __str__ __format__ __bool__ __hash__ __eq__ __ne__ __lt__ __le__ __gt__ __ge__ __add__ __sub__ __mul__ __matmul__ __truediv__ __floordiv__ __mod__ __pow__ __and__ __or__ __xor__ __lshift__ __rshift__ __neg__ __pos__ __abs__ __invert__ __radd__ (r-variants) __iadd__ (i-variants) __int__ __float__ __index__ __round__ __len__ __getitem__ __setitem__ __delitem__ __contains__ __iter__ __next__ __reversed__ __missing__ __call__ __enter__ __exit__ __getattr__ __getattribute__ __setattr__ __delattr__ __dir__ __copy__ __deepcopy__ __getstate__ __setstate__ __reduce__ __class_getitem__ __init_subclass__ __match_args__ __slots__
Descriptors & __slots__
Descriptor
An object that customises attribute access on another class.
class Positive:
def __set_name__(self, owner, name): self.name = "_" + name
def __get__(self, obj, objtype=None):
return self if obj is None else getattr(obj, self.name)
def __set__(self, obj, value):
if value <= 0: raise ValueError
setattr(obj, self.name, value)
class Item:
price = Positive()
__slots__
Fixed attributes, saves memory, no per-instance dict.
class P:
__slots__ = ("x", "y")Metaclasses
Custom metaclass
A class whose instances are classes.
class Meta(type):
def __new__(mcs, name, bases, ns, **kw):
return super().__new__(mcs, name, bases, ns)
def __call__(cls, *a, **k):
return super().__call__(*a, **k)
class A(metaclass=Meta): ...
Dynamic class & hooks
Create classes at runtime; react to subclassing.
Dyn = type("Dyn", (object,), {"x": 1})
class Base:
def __init_subclass__(cls, **kw): super().__init_subclass__(**kw)
def class_deco(cls): cls.tag = 1; return cls
@class_deco
class B: ...Async / await
Coroutines
Functions that can pause while waiting.
async def fetch():
await something()
return 1
Async iteration & context
Async versions of for, with and comprehensions.
async def agen():
yield 1
async for x in agen(): ...
async with ctx as c: ...
[x async for x in agen()]
class AC:
async def __aenter__(self): ...
async def __aexit__(self, *a): ...
def __aiter__(self): ...
async def __anext__(self): ...Two-way generators
send, throw, close
Generators can receive values and errors.
def acc():
total = 0
while True:
x = yield total
total += x
g = acc(); next(g)
g.send(5) g.throw(ValueError) g.close()
r = yield from sub() # delegate and capture returnException groups (3.11+)
except*
Handle several errors raised together.
try:
raise ExceptionGroup("many", [ValueError(1), TypeError(2)])
except* ValueError as eg: ...
except* TypeError as eg: ...
e.add_note("extra context")
e.__cause__ e.__context__ e.__traceback__Type hints & generics
Annotations
Optional hints for tools and readers.
def f(a: list[int], b: dict[str, int] | None = None) -> tuple[int, ...]: ... from typing import Any, Optional, Union, Callable, Literal, Final from typing import TypedDict, Protocol, Generic, TypeVar, ClassVar, Self, Annotated
Generics
Write code that works for any type.
T = TypeVar("T")
class Box(Generic[T]): ...
def first[T](xs: list[T]) -> T: ... # 3.12+
class Stack[T]: ...
type Alias = list[int] # 3.12+Dynamic features
eval, exec, introspection
Run and inspect code at runtime.
eval("1 + 2") exec("x = 1") compile(src, "f", "exec")
globals() locals() id(x) hash(x) callable(f)
f.__name__ f.__doc__ f.__annotations__ f.__defaults__
__import__("os") breakpoint()Keywords
All reserved words
Names you cannot use as variables.
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 # soft keywords: match case _ type