List comprehensions, a reversed join(), and KeyError instead of undefined. Small syntax, but the idioms took real unlearning.
Stop writing JavaScript in Python
Comprehensions, a reversed join(), and KeyError
This is post 3 of my TypeScript-to-Python journey. Old habits die hard however, Python keep telling me to stop writing JavaScript in it.
Quick background: I am a full-stack developer expanding into AI engineering, learning Python by building GenAI apps directly. Today was about the everyday plumbing: filtering data and assembling prompts, which is 70% of what LLM application code does.
My instinct after ten years of TypeScript:
Python has map() and filter() too, but the community considers them unidiomatic. The Pythonic way is a comprehension: one expression that does both.
It reads strangely for the first hour. Very counter-intuitive. Until i realized what is it about and how to wrap my head around it.
Notice the reading order of a comprehension: EXPRESSION, then for-loop, then filter. "Give me j["title"], for each j in jobs, if job is remote." The filter comes last even though it runs first.
Two things very interesting thing that I learnt:
1. join() is reversed. It is not list.join("\n"), it is "\n".join(list). The separator string owns the method, not the list.
TypeScript
Python
2. Missing dict keys throw KeyError instead of returning undefined. So config.get("model", fallback) is the Python way of config.model ?? fallback.
TypeScript
Python
dict["key"]raisesKeyErrorif the key is missing.dict.get("key", fallback)is the safe version, with the fallback as the second argument instead of a??operator.
f-strings are python way of template literals, it beats template literals for formatting. f"{salary:,}" prints 195,000 with the thousands separator baked in, no library needed.
Template literals cannot do that on their own.
A script that loads AI-engineer job postings from JSON, filters the remote Python ones with a comprehension, and assembles a formatted prompt using f-strings. Small thing, but this is the exact shape of prompt assembly inside every RAG pipeline, so I will be reusing this muscle weekly.
I created a jobs.json
Then wrote a script to create the prompt for the AI
Syntax is easy, unlearning hard. The second part is where the actual work is.
The type hints are the middleware
FastAPI, from an Express developer's point of view
The last post in the series. I rebuilt my Express reflexes in FastAPI, found the type hints doing the validation, the docs, and the serializing, then made it stream.
You start it
async/await, but the event loop is not ambient anymore
async/await transfers almost 1:1 from JS, but Python's event loop is not ambient. Two gotchas from wiring up token-by-token streaming.
Zod taught me Pydantic
Define the schema, parse at the boundary. Same mental model, new language.
If you have used Zod, you already understand 70 to 80% of Pydantic. The mental model transfers almost one-to-one.