Python for PHP developers

The syntax shift, mapped from what you already know · Python 3.13

Cheat sheet · DocChat capstone · keep this pinned · indentation is the syntax — 4 spaces, no braces, no semicolons, no $

Variables & strings

PHP → Python

// PHP            # Python
$name = "Sam";    name = "Sam"
$n = 5;           n = 5
$ok = true;       ok = True        # True/False/None
.  (concat)       +   or  f-string

f-strings (use these, not concat)

name = "Sam"; age = 30
f"Hi {name}, age {age}"      # Hi Sam, age 30
f"{age * 2}"                 # 60
f"{price:.2f}"               # 19.90  (2 decimals)
f"{name=}"                   # name='Sam'  (debug)

Lists & dicts

nums = [1, 2, 3]            # list  (PHP indexed array)
nums.append(4)             # push
nums[0]      # 1     nums[-1]   # last = 4
nums[1:3]    # [2, 3]  (slice: start:stop)
len(nums)    # 4

user = {"name": "Sam", "age": 30}   # dict
user["name"]                # "Sam"
user.get("x", "default")    # safe, no KeyError
user["city"] = "Dubai"      # add/update
for k, v in user.items(): ...

List comprehensions

The Pythonic foreach+map+filter.

squares = [n*n for n in range(5)]      # [0,1,4,9,16]
evens   = [n for n in nums if n % 2 == 0]
names   = [u["name"] for u in users]
# dict comprehension
by_id   = {u["id"]: u for u in users}

Control flow

if age >= 18:
    print("adult")
elif age > 12:
    print("teen")
else:
    print("child")

for i in range(3):      # 0, 1, 2
    print(i)

for item in nums:       # foreach
    print(item)

while n > 0:
    n -= 1              # no ++ / --
# combine: and / or / not  (not && || !)

Functions

def greet(name, greeting="Hi"):     # default arg
    return f"{greeting}, {name}"

greet("Sam")                  # "Hi, Sam"
greet("Sam", greeting="Yo")   # keyword arg

def total(*args, **kwargs):
    # args  -> tuple of positional  (1, 2, 3)
    # kwargs-> dict of named        {"tax": 5}
    return sum(args)

total(1, 2, 3, tax=5)         # 6

Classes & dataclass

class User:
    def __init__(self, name, age):   # constructor
        self.name = name             # self == $this
        self.age = age
    def greet(self):
        return f"Hi {self.name}"

u = User("Sam", 30)     # no 'new' keyword
u.greet()

dataclass — less boilerplate (you'll see this in Pydantic next)

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int = 0          # default
# __init__, __repr__, __eq__ generated for you
u = User("Sam", 30)

Errors: try / except

try:
    x = int("oops")
except ValueError as e:
    print(f"bad: {e}")
except (KeyError, TypeError):
    ...
else:
    ...            # ran if no error
finally:
    ...            # always runs
raise ValueError("custom message")

Imports & modules

import math                 # math.sqrt(9)
from datetime import date   # date.today()
from .models import User    # local module
import json as j            # alias
# a file = a module; a folder w/ files = a package

Type hints

def add(a: int, b: int) -> int:
    return a + b

name: str = "Sam"
tags: list[str] = []
conf: dict[str, int] = {}
from typing import Optional
mid: Optional[int] = None   # or: int | None
Hints are optional & not enforced at runtime — but FastAPI & Pydantic use them for validation. Write them everywhere.

Truthiness & None

Falsy (treated as false)Notes
False · None · 0 · 0.0 · "" · [] · {} · ()Empty collections are falsy — if items: checks "not empty".
None = PHP nullCompare with is: if x is None / if x is not None (not == None).
== vs is== compares value; is compares identity (use only for None/True/False).

Common built-ins

len(x)                       # length of str/list/dict
range(5)        # 0..4        range(2, 8, 2)  # 2,4,6
for i, v in enumerate(items):       # index + value
    print(i, v)
for a, b in zip(list1, list2):      # pair up
    print(a, b)
sorted(nums, reverse=True)   sum(nums)   max(nums)
"a,b,c".split(",")           ",".join(["a","b"])
str(5)  int("5")  float("5")  list(range(3))

virtualenv + pip (run in your project folder)

CommandWhat it does
python -m venv .venvCreate an isolated environment in .venv/
.venv\Scripts\activate (Win)
source .venv/bin/activate (mac/Linux)
Activate it — prompt shows (.venv)
pip install fastapiInstall a package into the active venv
pip freeze > requirements.txtSnapshot exact versions to a file
pip install -r requirements.txtReinstall everything from that file
deactivateLeave the venv
Always activate the venv first. Add .venv/ to .gitignore — commit requirements.txt, never the env folder.