⚡ The #1 Rule — Indentation IS Your Braces
Python uses 4 spaces (not tabs!) for code blocks. The colon : + indent replaces { }. Get this wrong and nothing runs.
# In Swift you have @main or AppDelegate# In Python:defmain():
print("App started")
if __name__ == "__main__":
main()
# Runs main() only when you execute THIS file directly,# not when another file imports it.
💡 iOS Dev Tip — Python Philosophy
Type import this in the REPL to see "The Zen of Python." Key idea: "There should be one obvious way to do it." Python prefers one clear way unlike Swift's multiple approaches.
print() Options
print("a", "b", "c") # a b cprint("a", "b", sep="-") # a-bprint("no newline", end="") # no \nprint(f"x = {42}") # x = 42
Input from User
# Like readLine() in Swift
name = input("Your name: ")
age = int(input("Age: "))
# input() always returns str!
02 Variables & Constants
🍎 Swift
var name: String = "Ali"let age: Int = 25
let PI = 3.14 // truly immutable
🐍 Python
name = "Ali"
AGE = 25 # convention only!
PI = 3.14 # nothing enforces it
⚡ No let vs var
Python has NO immutability keyword. UPPERCASE is just a "please don't change this" convention.
Type Hints OPTIONAL
name: str = "Ali"
age: int = 25
scores: list[int] = [90, 85]
maybe: str | None = None# like String?from typing import Optional
name: Optional[str] = None# same as str | None
Multiple Assignment & Naming
x, y, z = 1, 2, 3# multi assign
a, b = b, a # swap — no temp!
a = b = c = 0# same value# Swift: camelCase → Python: snake_case
my_variable = 10# variables
MY_CONSTANT = 3.14# constantsdefmy_function(): ... # functionsclassMyClass: ... # classes: PascalCase
_private_var = 5# _ prefix = "private"
🚨 Gotcha — Mutable Default Trapdef add(item, lst=[]): ← The [] is shared across ALL calls! def add(item, lst=None): ← Do this instead, then lst = lst or [] inside.
03 Data Types — Complete Map
Python
Swift
Notes
int
Int
Unlimited precision! No overflow
float
Double
Always 64-bit
complex
—
z = 3+4j
str
String
Immutable, Unicode
bool
Bool
True/False capital!
bytes
Data
b"hello"
list
[Any]
Mutable, ordered
tuple
(Int, String)
Immutable
dict
[String: Any]
Key-value, ordered (3.7+)
set
Set<Int>
Unique unordered
frozenset
—
Immutable set
None
nil
The null value
💡 No Integer Overflow!2 ** 1000 just works in Python. No Int.max, no overflow. Great for algorithms.
nums = [1, 2, 3, 4, 5]
repeated = [0] * 10# Array(repeating:count:)# Add
nums.append(6) # add one
nums.extend([7, 8]) # add many → .append(contentsOf:)
nums.insert(0, 99) # insert at index# Remove
nums.remove(99) # by VALUE
nums.pop() # last → .removeLast()
nums.pop(0) # first → .removeFirst()del nums[2] # by index
nums.clear() # all → .removeAll()# Access
nums[0] nums[-1] # first / LAST
nums[1:4] # slice# Search & Sort3in nums # .contains(3)
nums.index(3) # .firstIndex(of:)sorted(nums) # NEW sorted → .sorted()
nums.sort(reverse=True) # in-place desc# Aggregatelen(nums) min(nums) max(nums) sum(nums)
List Comprehensions ⭐ PYTHON'S SUPERPOWER
# Map: nums.map { $0 * 2 }
doubled = [x * 2for x in nums]
# Filter: nums.filter { $0 % 2 == 0 }
evens = [x for x in nums if x % 2 == 0]
# Map+Filter combined
result = [x * 2for x in nums if x % 2 == 0]
# CompactMap: items.compactMap { $0 }
cleaned = [x for x in items if x is notNone]
# FlatMap: [[1,2],[3,4]].flatMap { $0 }
flat = [x for sub in nested for x in sub]
# Dict comprehension
squares = {x: x**2for x inrange(6)}
Dictionaries
user = {"name": "Ali", "age": 25}
user["name"] # "Ali" (KeyError if missing!)
user.get("phone", "N/A") # safe — like dict["k", default:]
user["email"] = "a@b.c"# add/update
user.update({"age": 26}) # merge
merged = {**d1, **d2} # spread mergedel user["age"] # remove
user.pop("age", None) # safe removefor k, v in user.items(): # iterate pairs"name"in user # key exists?
Tuples & Sets
# Tuples — immutable
point = (10, 20)
x, y = point # destructure# Named tuplesfrom collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(10, 20); p.x # 10# Sets
colors = {"red", "blue"}
colors.add("green")
colors.discard("red") # safe remove
a & b # intersection a | b # union
a - b # difference a ^ b # symmetric diff
collections Module — Power Tools BONUS
from collections import Counter, defaultdict, deque
Counter("banana") # {'a':3, 'n':2, 'b':1}
Counter("banana").most_common(2)
dd = defaultdict(list)
dd["fruits"].append("apple") # no KeyError!
q = deque([1,2,3])
q.appendleft(0) # O(1) vs list's O(n)
06 Control Flow
🍎 Swift
if score > 90 {
print("A")
} else if score > 80 {
print("B")
} else {
print("C")
}
for i in0..5 { }
for (i,v) in arr.enumerated() { }
🐍 Python
if score > 90:
print("A")
elif score > 80:
print("B")
else:
print("C")
for i inrange(5):
for i, v inenumerate(arr):
# Enumerate with startfor i, item inenumerate(fruits, start=1):
print(f"{i}. {item}")
# Zip — pair two listsfor name, age inzip(names, ages):
print(f"{name} is {age}")
# Reversedfor item inreversed(nums): ...
# for/else — unique to Python!for item in items:
if item == target: breakelse:
print("Not found!") # runs if NO break
Operators & Ternary
# Logical: and, or, not (not &&, ||, !)# Chained comparison — Python exclusive!if0 < x < 100: # clean!if1 <= age <= 120:
# Ternary (reversed from Swift!)
r = "yes"if x > 0else"no"# Identity
x isNone x is notNone
match/case PYTHON 3.10+
match command:
case"quit": exit()
case"hello" | "hi": print("Hi!")
case [x, y]: print(f"pair: {x},{y}")
case {"name": name}: print(name)
case _: print("default")
⚡ Key Differences
1. Every method needs explicit self · 2. Constructor is __init__ · 3. No new keyword · 4. Properties created inside __init__ · 5. No access modifiers — use _ convention
Inheritance & @property
classPuppy(Dog): # class Puppy: Dogdef__init__(self, name, toy):
super().__init__(name) # super.init(name:)self.toy = toy
defbark(self): # override (no keyword!)returnf"{self.name} yips!"# Computed propertyclassCircle:
def__init__(self, r): self._r = r
@propertydefarea(self): # var area: Double { }return3.14159 * self._r ** 2@propertydefradius(self): returnself._r
@radius.setterdefradius(self, val):
if val < 0: raiseValueErrorself._r = val
💡 EAFP vs LBYL
Swift: "Look Before You Leap" (if let, guard). Python: "Easier to Ask Forgiveness" — just try it and catch errors. try/except is normal flow control in Python.
13 Modules, Packages & Imports
Import Styles
import os # whole modulefrom os import path # specific itemfrom os import path as p # aliasimport json as j # module alias
# Writewithopen("out.txt", "w") as f:
f.write("Hello\n")
# Read allwithopen("out.txt") as f:
content = f.read()
# Read line by line (memory efficient)withopen("big.txt") as f:
for line in f:
print(line.strip())
# Appendwithopen("log.txt", "a") as f: ...
# Binary (like Data in Swift)withopen("img.png", "rb") as f: data = f.read()
⚡ Always use with — it auto-closes the file like defer.
JSON — Way Easier Than Codable
import json
data = {"name": "Ali", "age": 25}
json_str = json.dumps(data, indent=2) # → JSON string
obj = json.loads(json_str) # → dict# File I/Owithopen("data.json") as f: data = json.load(f)
withopen("data.json","w") as f: json.dump(data, f, indent=2)
pathlib — Modern Paths ⭐ USE THIS
from pathlib import Path
p = Path("docs") / "report.txt"# like URL!
p.exists() p.is_file() p.is_dir()
p.write_text("Hello")
content = p.read_text()
p.name p.stem p.suffix p.parent
for f in Path(".").glob("*.py"): print(f)
Path("output").mkdir(exist_ok=True)
import asyncio, aiohttp
async deffetch() -> dict:
async with aiohttp.ClientSession() as s:
async with s.get(url) as r:
return await r.json()
asyncio.run(fetch())
Concurrent Tasks
async defmain():
# Run 3 tasks at once (like async let / TaskGroup)
results = await asyncio.gather(
fetch(1), fetch(2), fetch(3)
)
# With timeouttry:
r = await asyncio.wait_for(fetch(1), timeout=5)
except asyncio.TimeoutError: ...
💡 Python async is single-threaded (event loop, like JS). For CPU-heavy work use multiprocessing. Async is best for I/O.
16 Generators & Iterators PYTHON EXCLUSIVE
yield — Lazy Sequences
defcountdown(n):
while n > 0:
yield n # pauses, returns n
n -= 1for x incountdown(5): print(x) # 5,4,3,2,1# Generator expression — lazy list comprehension
squares = (x**2for x inrange(1_000_000))
# Uses almost NO memory!next(squares) # 0next(squares) # 1# Practical — read huge filesdefread_big(path):
withopen(path) as f:
for line in f: yield line.strip()
💡 Like AsyncSequence but synchronous.range(), enumerate(), zip(), map() all return generator-like objects!
17 Decorators — Like Property Wrappers
How They Work
import time
deftimer(func):
defwrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.2f}s")
return result
return wrapper
@timerdefslow(): time.sleep(1)
slow() # "slow took 1.00s"
Built-in Decorators You'll Use
@property# computed property@staticmethod# static func@classmethod# factory/convenience init@dataclass# auto init/repr/eq@abstractmethod# protocol requirementfrom functools import cache
@cache# memoization — caches resultsdeffib(n):
if n < 2: return n
returnfib(n-1) + fib(n-2)
fib(100) # instant! (without @cache = impossibly slow)
18 HTTP & API Calls YOUR URLSession
requests Library
# pip install requestsimport requests
# GET
r = requests.get("https://api.example.com/users")
r.status_code# 200
data = r.json() # auto-decode → dict# GET with params
r = requests.get(url, params={"q": "python", "page": 1})
# POST with JSON
r = requests.post(url,
json={"name": "Ali"},
headers={"Authorization": "Bearer TOKEN"}
)
r.raise_for_status() # raises on 4xx/5xx
# ❌ if len(lst) > 0: / if name != "":# ✅ if lst: / if name: / if x is not None:
2. Unpacking
first, *rest = [1,2,3,4] # first=1, rest=[2,3,4]
a, b = b, a # swapfunc(*args, **kwargs) # spread into call
3. Walrus Operator :=
if (n := len(data)) > 10:
print(f"Too long: {n}")
while (line := f.readline()) != "":
process(line)
4. One-Liners
any(x > 0for x in nums) # any match?all(x > 0for x in nums) # all match?min(users, key=lambda u: u.age) # min by keyif18 <= age <= 65: # chained comparison
{**d1, **d2} # merge dicts"hello"[::-1] # reverse string
[x for sub in nested for x in sub] # flattenlist(dict.fromkeys(items)) # unique, keep order
5. Debug Print (3.8+)
x = 42print(f"{x=}") # "x=42" self-documenting!print(f"{x=}, {type(x)=}") # "x=42, type(x)=<class 'int'>"breakpoint() # drops into debugger (pdb)
6. Pattern Translation Table
Swift
Python
guard let x = y else { return }
if y is None: return; x = y
.compactMap { $0 }
[x for x in arr if x is not None]
.first(where: { $0 > 5 })
next((x for x in arr if x > 5), None)
.contains(where: { $0 > 5 })
any(x > 5 for x in arr)
.allSatisfy { $0 > 0 }
all(x > 0 for x in arr)
defer { }
try/finally or with
extension
Just add methods (monkey-patch)
enum + associated values
dataclass subclasses or match/case
21 Complete Quick Reference
Python
Swift
What
def
func
Define function
self
self
Instance ref (explicit!)
__init__
init
Constructor
None
nil
Null
True / False
true / false
Booleans (CAPITAL!)
and / or / not
&& / || / !
Logic
elif
else if
Else-if
len(x)
x.count
Length
range(n)
0..<n
Range
enumerate()
.enumerated()
Index+value
zip(a,b)
zip(a,b)
Pair sequences
isinstance()
is / as?
Type check
raise
throw
Throw error
except
catch
Catch error
finally
defer
Always runs
pass
—
Empty block
print()
print()
Same! 🎉
import
import
Import
pip
SPM/Pods
Package mgr
@property
var { get }
Computed prop
@staticmethod
static func
Static method
@classmethod
convenience init
Factory
@dataclass
struct
Data container
lambda
{ closure }
Anonymous func
f"...{x}"
"\(x)"
Interpolation
with open()
—
Auto-close context
x if c else y
c ? x : y
Ternary
**
pow()
Power
//
Int(a/b)
Floor division
yield
—
Generator
async def
async func
Async function
await
await
Await result
assert
XCTAssert
Test assertion
breakpoint()
lldb
Debugger
[x for x in]
.map { }
Comprehension
is / is not
=== / !==
Identity
in
.contains()
Membership
snake_case
camelCase
Naming
You're ready to Python 🐍
Made for Swift devs who want to learn Python fast ⚡