FULL STACK CITY

The Academy · 6 min read

Python for JavaScript developers: the FastAPI survival kit

Variables without let or const, dicts vs objects, functions, classes with type hints and async/await: the Python a JavaScript developer needs for FastAPI.

Variables without let or const

Byte: You already know how to program. This is just a new accent.

Python has no let, const or var. You assign with = and the name exists. Types are still dynamic, like JavaScript.

Backend code adds type hints after a colon. Python itself doesn't enforce them, but FastAPI and Pydantic read them to validate data, which is why you'll see them everywhere in this city.

variables.py
name = "Neo" # like: let name = "Neo"
age: int = 25 # type hint: age should be an int
is_admin: bool = False # True / False are capitalised
nothing = None # Python's null
Quick check: Which line is valid Python?
  • let age = 25
  • age = 25
  • const age = 25

Python has no declaration keyword. age = 25 creates the variable.

Dicts are objects, lists are arrays

Byte: JSON maps straight onto these two.

A dict is Python's version of a JavaScript object, and a list is an array. A JSON request body becomes dicts and lists.

One big difference: you read dict keys with square brackets and quotes. Dot access (user.name) works on objects and classes, not on dicts.

data.py
user = {"name": "Neo", "roles": ["admin", "editor"]}
user["name"] # "Neo"
user["roles"][0] # "admin"
len(user["roles"]) # 2 (like .length)
Quick check: With user = {"name": "Neo"}, how do you read the name?
  • user.name
  • user["name"]

Dicts use square brackets. user.name would raise an AttributeError.

Functions and indentation

Byte: Indentation is the braces.

Functions start with def, and the body is whatever is indented under the colon. There are no curly braces, so indentation is part of the syntax: four spaces per level.

if, for and class work the same way: a colon, then an indented block.

functions.py
def greet(name: str) -> str:
if name == "":
return "Hello, stranger"
return f"Hello, {name}" # f-string, like `Hello, ${name}`
Quick check: What marks where a Python function body ends?
  • A closing curly brace
  • The indentation going back out
  • The word end

When the indentation returns to the outer level, the block is over.

Classes with type hints

Byte: Pydantic models are just classes like these.

A class groups data and behaviour. In backend code you'll often write classes that are mostly a list of typed fields. That's exactly what a Pydantic model is.

BaseModel in the brackets means the class extends it, like class User extends BaseModel in JavaScript.

models.py
from pydantic import BaseModel
class User(BaseModel): # extends BaseModel
name: str
age: int
neo = User(name="Neo", age=25)
neo.name # "Neo" (dot access works on classes)
Quick check: In class User(BaseModel):, what is BaseModel?
  • A parameter passed to User
  • The class User extends
  • A decorator

The brackets after a class name list what it inherits from.

async and await

Byte: Same idea as in JavaScript.

Python has async functions and await, and they mean what you expect: wait for slow work (a database, a network call) without blocking the server.

FastAPI route handlers are usually async def. You'll see them in every district from here on.

handler.py
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = await db.fetch_user(user_id) # like: await db.fetchUser(id)
return user
Quick check: What is async def closest to in JavaScript?
  • async function
  • new Promise
  • setTimeout

An async def function returns something you can await, just like an async function.