Core Syntax Rules
For Loops & Control Flow
Functions & Decorators
Classes & OOP
Error Handling
Modern & Clever Features (3.8+)
Modifying Lists
File System Interaction
Math Tools
Standard Library Tour
String Formatting Through the Ages
if True :
x = 1
if True :
y = 2
x = "global"
def outer ():
x = "enclosing"
def inner ():
x = "local"
print (x )
inner ()
count = 0
def increment ():
global count
count += 1
def outer ():
x = 0
def inner ():
nonlocal x
x += 1
inner ()
def f (x ):
x += 1
a = 5
f (a )
print (a ) # 5
def g (lst ):
lst .append (4 )
b = [1 , 2 , 3 ]
g (b )
print (b ) # [1, 2, 3, 4]
def f (items = []):
items .append (1 )
return items
def f (items = None ):
items = items if items is not None else []
if []: ...
if "0" : ...
if 0.0 : ...
a = [1 , 2 ]
b = [1 , 2 ]
a == b # True
a is b # False
x = None
x is None
a = 256 ; b = 256
a is b # True
a = 257 ; b = 257
a is b # False
1 < 2 < 3
2 + 3 * 4 # 14
2 ** 3 ** 2 # 512
x = None
y = x or "default"
z = a and b
7 / 2 # 3.5
7 // 2 # 3
7 % 2 # 1
- 7 // 2 # -4
- 7 % 2 # 1
'single' == "double"
"""triple"""
"a" "b"
s = "hello"
s [0 ] # 'h'
s [0 ] = 'H' # error
r"raw\nstring"
b"bytes"
def f (): pass
f .__name__
type (f )
isinstance (5 , int )
callable (f )
funcs = [str .upper , str .lower ]
funcs [0 ]("hi" )
a = b = c = 0
a , b = b , a
x : int = 5
x : int
1 == 1.0 # True
True == 1 # True
"1" == 1 # False
def f (a , b = 1 , * args , c , d = 2 , ** kwargs ):
...
f (1 , c = 3 )
f (1 , 2 , 3 , 4 , c = 5 , e = 6 )
def f (a , b = 1 , c ): # SyntaxError
...
Positional-only / keyword-only
def f (a , b , / , c , * , d ):
...
def f (a , b , c ): ...
args = [1 , 2 , 3 ]
f (* args )
kwargs = {"a" : 1 , "b" : 2 , "c" : 3 }
f (** kwargs )
first , * rest = [1 , 2 , 3 , 4 ]
merged = [* list1 , * list2 ]
merged_dict = {** d1 , ** d2 }
funcs = [lambda : i for i in range (3 )]
[f () for f in funcs ] # [2, 2, 2]
funcs = [lambda i = i : i for i in range (3 )]
[f () for f in funcs ] # [0, 1, 2]
Comments & docstrings
# comment
def f ():
"""Docstring."""
pass
a = 1 ; b = 2
total = 1 + \
2 + \
3
total = (1 +
2 +
3 )
for item in [1 , 2 , 3 ]:
print (item )
for i in range (5 ):
for i in range (2 , 10 , 2 ):
for i in range (10 , 0 , - 1 ):
n = 5
while n > 0 :
print (n )
n -= 1
for x in items :
if x is None :
continue
if x == "stop" :
break
for x in items :
if x == target :
break
else :
print ("not found" )
for i , row in enumerate (grid ):
for j , val in enumerate (row ):
print (i , j , val )
for key in d :
for key , val in d .items ():
for val in d .values ():
for name , age in zip (names , ages ):
print (name , age )
for x in reversed ([1 , 2 , 3 ]):
print (x )
for p in sorted (people , key = lambda p : p .age , reverse = True ):
print (p )
if x > 0 :
sign = "positive"
elif x < 0 :
sign = "negative"
else :
sign = "zero"
if "a" in "cat" : ...
if x not in blacklist : ...
while True :
cmd = input ("> " )
if cmd == "quit" :
break
result = []
for x in items :
if x > 0 :
result .append (x )
result = [x for x in items if x > 0 ]
for x in items :
pass
for x , y in [(1 , 2 ), (3 , 4 )]:
print (x + y )
def timer (func ):
def wrapper (* args , ** kwargs ):
start = time .time ()
result = func (* args , ** kwargs )
print (time .time () - start )
return result
return wrapper
@timer
def slow (): ...
from functools import wraps
def decorator (func ):
@wraps (func )
def wrapper (* a , ** kw ): return func (* a , ** kw )
return wrapper
def make_counter ():
count = 0
def increment ():
nonlocal count
count += 1
return count
return increment
from functools import partial
add5 = partial (lambda a , b : a + b , 5 )
add5 (10 )
from functools import reduce
reduce (lambda a , b : a * b , [1 ,2 ,3 ,4 ])
sorted (people , key = lambda p : p .age )
list (map (str .upper , words ))
list (filter (lambda x : x > 0 , nums ))
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 __repr__ (self ): return f"Vec({ self .x } , { self .y } )"
def __eq__ (self , o ): return (self .x , self .y ) == (o .x , o .y )
class Circle :
def __init__ (self , r ): self ._r = r
@property
def area (self ): return 3.14159 * self ._r ** 2
class Date :
@classmethod
def from_string (cls , s ): return cls (* map (int , s .split ("-" )))
@staticmethod
def is_valid (s ): return len (s .split ("-" )) == 3
class Countdown :
def __init__ (self , n ): self .n = n
def __iter__ (self ): return self
def __next__ (self ):
if self .n <= 0 : raise StopIteration
self .n -= 1
return self .n + 1
class Timer :
def __enter__ (self ): self .start = time .time (); return self
def __exit__ (self , * exc ): print (time .time () - self .start )
with Timer ():
do_work ()
from contextlib import contextmanager
@contextmanager
def open_resource ():
r = acquire ()
try :
yield r
finally :
release (r )
class A : pass
class B : pass
class C (A , B ): pass
print (C .__mro__ )
from abc import ABC , abstractmethod
class Shape (ABC ):
@abstractmethod
def area (self ): ...
class Positive :
def __set_name__ (self , owner , name ): self .name = name
def __get__ (self , obj , type = None ): return obj .__dict__ [self .name ]
def __set__ (self , obj , value ):
if value < 0 : raise ValueError ("must be positive" )
obj .__dict__ [self .name ] = value
class Product :
price = Positive ()
class Meta (type ):
def __new__ (mcs , name , bases , ns ):
ns ['created_by' ] = 'Meta'
return super ().__new__ (mcs , name , bases , ns )
class Foo (metaclass = Meta ): pass
try :
risky ()
except ValueError as e :
handle (e )
else :
print ("no error occurred" )
finally :
cleanup ()
class InsufficientFundsError (Exception ):
def __init__ (self , amount ):
self .amount = amount
super ().__init__ (f"short by { amount } " )
try :
parse (data )
except ValueError as e :
raise ConfigError ("bad config" ) from e
try :
...
except* ValueError as eg :
for e in eg .exceptions :
print (e )
Modern & Clever Features (3.8+)
if (n := len (data )) > 10 :
print (f"too long: { n } " )
match command .split ():
case ["go" , direction ]:
move (direction )
case ["attack" , * targets ]:
attack (targets )
case {"action" : "jump" , "height" : h }:
jump (h )
case Point (x = 0 , y = 0 ):
print ("origin" )
case _:
print ("unknown" )
x = 5
print (f"{ x = } " )
def first (items : list [int ]) -> int | None :
return items [0 ] if items else None
type Vector = list [float ]
from dataclasses import dataclass
@dataclass (slots = True , frozen = True )
class Point :
x : float
y : float
from functools import cache
@cache
def fib (n ): return n if n < 2 else fib (n - 1 ) + fib (n - 2 )
merged = dict_a | dict_b
dict_a |= dict_b
first , * middle , last = [1 , 2 , 3 , 4 , 5 ]
with open ("a" ) as a , open ("b" ) as b :
...
from contextlib import suppress
with suppress (FileNotFoundError ):
os .remove ("gone.txt" )
from enum import Enum , auto
class Color (Enum ):
RED = auto ()
GREEN = auto ()
from itertools import pairwise , batched
list (pairwise ([1 ,2 ,3 ,4 ]))
list (batched (range (7 ), 3 ))
def flatten (nested ):
for item in nested :
yield from item
import asyncio
async def main ():
async with asyncio .TaskGroup () as tg :
tg .create_task (fetch (url1 ))
tg .create_task (fetch (url2 ))
from typing import Self
class Builder :
def add (self , x ) -> Self :
return self
from typing import Protocol
class Sized (Protocol ):
def __len__ (self ) -> int : ...
lst = [1 , 2 , 3 ]
lst .append (4 )
lst .insert (1 , "x" )
lst .extend ([5 , 6 ])
lst += [7 , 8 ]
lst = lst + [9 ]
lst .remove ("x" )
lst .pop ()
lst .pop (0 )
del lst [0 ]
del lst [1 :3 ]
lst .clear ()
lst [0 ] = 100
lst [1 :3 ] = [10 , 20 , 30 ]
lst [::2 ] = [0 , 0 , 0 ]
lst .sort ()
lst .sort (reverse = True )
lst .sort (key = lambda x : - x )
lst .reverse ()
sorted (lst )
list (reversed (lst ))
lst .index (3 )
lst .count (3 )
3 in lst
a = [1 , 2 , 3 ]
b = a
b .append (4 )
c = a .copy ()
c = a [:]
import copy
d = copy .deepcopy (a )
lst .sort ()
new = sorted (lst )
lst .append (5 )
new = lst + [5 ]
doubled = [x * 2 for x in lst ]
filtered = [x for x in lst if x > 0 ]
lst [:] = [x for x in lst if x > 0 ]
combined = lst1 + lst2
lst1 .extend (lst2 )
lst [:] = list (dict .fromkeys (lst ))
grid = [[0 ]* 3 for _ in range (3 )]
grid [0 ][1 ] = 5
import numpy as np
arr = np .array ([1 , 2 , 3 ])
arr [0 ] = 100
arr = np .append (arr , 4 )
arr = np .delete (arr , 1 )
arr = np .insert (arr , 0 , - 1 )
arr += 10
mask = arr > 0
arr = arr [mask ]
from pathlib import Path
p = Path ("data/file.txt" )
p .exists ()
p .is_file ()
p .is_dir ()
p .name
p .stem
p .suffix
p .parent
p .resolve ()
p .mkdir (parents = True , exist_ok = True )
p .write_text ("hello" )
content = p .read_text ()
p .write_bytes (b"data" )
for f in Path ("." ).iterdir ():
print (f )
for f in Path ("." ).glob ("**/*.py" ):
print (f )
with open ("file.txt" ) as f :
content = f .read ()
lines = f .readlines ()
for line in f :
process (line )
with open ("out.txt" , "w" ) as f :
f .write ("hello\n " )
with open ("log.txt" , "a" ) as f :
f .write ("more\n " )
import os
os .getcwd ()
os .chdir ("/tmp" )
os .listdir ("." )
os .rename ("old.txt" , "new.txt" )
os .remove ("file.txt" )
os .path .join ("dir" , "file.txt" )
os .path .getsize ("file.txt" )
os .walk ("." )
for root , dirs , files in os .walk ("." ):
for f in files :
print (os .path .join (root , f ))
import shutil
shutil .copy ("a.txt" , "b.txt" )
shutil .copytree ("src_dir" , "dst_dir" )
shutil .move ("a.txt" , "archive/" )
shutil .rmtree ("old_dir" )
shutil .make_archive ("backup" , "zip" , "my_folder" )
import tempfile
with tempfile .TemporaryDirectory () as d :
...
with tempfile .NamedTemporaryFile (delete = False ) as f :
f .write (b"data" )
import zipfile
with zipfile .ZipFile ("archive.zip" ) as z :
z .extractall ("out/" )
z .namelist ()
import tarfile
with tarfile .open ("archive.tar.gz" ) as t :
t .extractall ("out/" )
import math
math .sqrt (16 )
math .pow (2 , 10 )
math .floor (3.7 ), math .ceil (3.2 )
math .log (100 , 10 )
math .exp (1 )
math .factorial (5 )
math .gcd (12 , 18 )
math .isclose (0.1 + 0.2 , 0.3 )
math .pi , math .e , math .inf , math .nan
math .hypot (3 , 4 )
import statistics as stats
stats .mean ([1 , 2 , 3 , 4 ])
stats .median ([1 , 2 , 3 , 4 ])
stats .mode ([1 , 1 , 2 , 3 ])
stats .stdev ([1 , 2 , 3 , 4 ])
stats .variance ([1 , 2 , 3 , 4 ])
import random
random .random ()
random .uniform (1 , 10 )
random .randint (1 , 6 )
random .choice (["a" ,"b" ,"c" ])
random .sample (range (100 ), 5 )
random .shuffle (my_list )
random .seed (42 )
from decimal import Decimal , getcontext
getcontext ().prec = 10
Decimal ("0.1" ) + Decimal ("0.2" )
from fractions import Fraction
Fraction (1 , 3 ) + Fraction (1 , 6 )
Fraction (0.5 )
import cmath
cmath .sqrt (- 1 )
import numpy as np
arr = np .array ([1 , 2 , 3 ])
np .mean (arr ), np .std (arr ), np .sum (arr )
np .dot (a , b )
np .linalg .inv (matrix )
np .linalg .solve (A , b )
arr .reshape (3 , 1 )
np .arange (0 , 10 , 0.5 )
np .linspace (0 , 1 , 100 )
from scipy import optimize , stats
optimize .minimize (func , x0 )
stats .norm .pdf (x , loc = 0 , scale = 1 )
stats .ttest_ind (sample1 , sample2 )
from collections import Counter , defaultdict , namedtuple , deque , OrderedDict , ChainMap
Counter ("banana" )
defaultdict (int )
deque ([1 ,2 ,3 ], maxlen = 5 )
from itertools import chain , product , combinations , permutations , groupby , islice
list (product ([1 ,2 ], ['a' ,'b' ]))
list (islice (range (100 ), 5 ))
import heapq
h = [3 ,1 ,4 ,1 ,5 ]
heapq .heapify (h )
heapq .heappush (h , 2 )
heapq .heappop (h )
import bisect
bisect .insort (sorted_list , 5 )
from functools import lru_cache , reduce , partial , cached_property
@lru_cache (maxsize = None )
def fib (n ): return n if n < 2 else fib (n - 1 )+ fib (n - 2 )
from operator import itemgetter , attrgetter
sorted (people , key = attrgetter ('age' ))
sorted (pairs , key = itemgetter (1 ))
import re
re .findall (r'\d+' , "a1 b22 c333" )
re .sub (r'\s+' , ' ' , "too many spaces" )
import textwrap
textwrap .fill (long_text , width = 40 )
import json
json .dumps ({"a" : 1 })
json .loads ('{"a": 1}' )
import csv
with open ("f.csv" ) as f :
for row in csv .reader (f ):
print (row )
from datetime import datetime , timedelta
now = datetime .now ()
now + timedelta (days = 7 )
now .strftime ("%Y-%m-%d" )
import time
time .sleep (1 )
time .time ()
import calendar
calendar .isleap (2024 )
import sys
sys .argv
sys .exit (1 )
sys .path
import subprocess
result = subprocess .run (["ls" , "-l" ], capture_output = True , text = True )
print (result .stdout )
import argparse
parser = argparse .ArgumentParser ()
parser .add_argument ("--name" , required = True )
args = parser .parse_args ()
import logging
logging .basicConfig (level = logging .INFO )
logging .info ("started" )
import threading
t = threading .Thread (target = worker )
t .start (); t .join ()
from multiprocessing import Pool
with Pool (4 ) as p :
results = p .map (func , data )
import asyncio
async def main ():
await asyncio .sleep (1 )
print ("done" )
asyncio .run (main ())
from concurrent .futures import ThreadPoolExecutor
with ThreadPoolExecutor () as ex :
results = list (ex .map (fetch , urls ))
from urllib .request import urlopen
urlopen ("https://example.com" ).read ()
import socket
s = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
import pickle
pickle .dumps (obj )
pickle .loads (data )
import hashlib
hashlib .sha256 (b"data" ).hexdigest ()
import base64
base64 .b64encode (b"data" )
import uuid
uuid .uuid4 ()
import unittest
class TestMath (unittest .TestCase ):
def test_add (self ):
self .assertEqual (1 + 1 , 2 )
def add (a , b ):
"""
>>> add(2, 3)
5
"""
return a + b
import pdb ; pdb .set_trace ()
import timeit
timeit .timeit ("sum(range(100))" , number = 10000 )
import copy
copy .deepcopy (nested_obj )
from typing import Optional , Union , Callable
def f (x : Optional [int ] = None ) -> Union [int , str ]: ...
from enum import Enum
class Color (Enum ):
RED = 1
GREEN = 2
from dataclasses import dataclass
@dataclass
class Point :
x : int
y : int
from contextlib import contextmanager , suppress
import inspect
inspect .signature (some_func )
inspect .getsource (some_func )
String Formatting Through the Ages
"%s is %d" % (name , age )
"{} is {}" .format (name , age )
f"{ name } is { age } "
f"{ name !r} is { age :>5} "