Python for JS Devs · Fundamentals
Keyword arguments are a first-class idea in Python — and one default-value gotcha catches every newcomer.
JS got default params and named-ish args (via object destructuring) later. Python had them from the start, and callers can pass any argument by name — a huge readability win you'll see all over FastAPI.
function connect(host, port = 5432,
{ ssl = false } = {}) {}
connect("db", 5432, { ssl: true });def connect(host, port=5432, ssl=False):
...
connect("db", ssl=True) # pass by name, skip portAny parameter can be passed positionally or by keyword. Passing by keyword (ssl=True) is idiomatic when it aids clarity — and FastAPI leans on it heavily.
*args and **kwargs — rest & spreadfunction log(...args) {}
log(...items);
fn({ ...opts });def log(*args, **kwargs): ...
log(*items) # spread a list into positionals
fn(**opts) # spread a dict into keywords*args collects extra positional args into a tuple; **kwargs collects extra keyword args into a dict. The */** also spread at the call site.
This is the classic Python bug, and it has no JS equivalent. Default argument values are evaluated once, at function-definition time — not on each call. So a mutable default (a list/dict) is shared across every call.
def add_item(item, cart=[]): # ⚠️ the [] is created ONCE
cart.append(item)
return cart
add_item("a") # → ['a']
add_item("b") # → ['a', 'b'] 😱 same list reused!
None, then create the real object inside the body:
def add_item(item, cart=None):
if cart is None:
cart = []
cart.append(item)
return cart
handlers = {"add": add_item} # store functions in dicts
sorted(users, key=lambda u: u["age"]) # lambda = one-expression fn
Lambdas are deliberately limited to a single expression. If you need more, use a named def — Python nudges you toward readable named functions.
In the REPL, paste the buggy add_item and call it twice to see the shared list. Then paste the fixed version and confirm each call starts fresh. Being able to say out loud "defaults evaluate once at def-time" is the win — it's a favourite interview question too.
param=None then if param is None: param = [] inside the function.**kwargs collects extra keyword args into a:**kwargs is a dict; *args is a tuple of extra positionals.* in a signature)? You'll see them in real APIs.