MISSION 1.1 · LEVEL 1 — PYTHON & DATA FOUNDATIONS
Python for Experienced Software Engineers
Python for developers who already write C#, Java, or TypeScript — tooling, project layout, typing, testing, and the idioms worth adopting (and the ones to skip).
PythonToolingFundamentals
Introduction
If you already write C#, Java, or TypeScript professionally, you do not need a “learn Python” course — you need a translation guide. The syntax takes a weekend. What takes longer is learning the tooling, the project conventions, and which habits transfer versus which need rewiring.
This mission is that guide, written specifically for engineers moving toward AI work — where Python is the lingua franca of every SDK, notebook, and framework you will touch.
Learning objectives
- Set up a Python environment the way production teams do (not the way tutorials do).
- Map concepts you know (LINQ, interfaces, NuGet, async/await) to Python equivalents.
- Adopt the idioms that matter in AI engineering codebases.
- Recognize the anti-patterns that mark “developer learning Python” code.
Environment and tooling: the production way
Tutorials teach pip install into a global interpreter. Production teams do this:
| Concern | Tool | C# / Node equivalent |
|---|---|---|
| Runtime version | pyenv / uv python | nvm, .NET SDK roll-forward |
| Virtual environments | python -m venv .venv / uv | Project-local packages by default |
| Dependencies | pyproject.toml + lockfile | package.json + lock, .csproj |
| Lint + format | ruff (both) | ESLint + Prettier |
| Type checking | mypy / pyright | TypeScript compiler |
| Testing | pytest | xUnit, Jest |
The modern, fast-moving default is uv (or Poetry) managing a pyproject.toml. The
conceptual key: a virtual environment is a per-project interpreter + dependency set, and
you activate it so python and pip resolve to the project, not the system.
# The production-shaped setup
uv init my-ai-service && cd my-ai-service
uv add fastapi pydantic anthropic
uv run pytest # runs inside the managed environment
If you remember one thing: never install project dependencies globally. Every “works on my machine” Python horror story starts there.
Concept translation table
| You know (C#/TS) | Python | Notes |
|---|---|---|
LINQ .Select/.Where | List comprehensions | [f(x) for x in xs if p(x)] — idiomatic and fast |
| Interfaces | Protocol (typing) | Structural typing — duck typing, checked |
| Abstract classes | abc.ABC | Use sparingly; protocols cover most cases |
| Generics | list[T], dict[K, V], TypeVar | Modern syntax (3.12+), fully typed |
| NuGet / npm | pip + PyPI | Always via the venv |
async/await | async/await + asyncio | Single-threaded event loop, like JS |
record types | dataclass / Pydantic BaseModel | Pydantic adds runtime validation |
| Exceptions | Exceptions (same idea) | Prefer specific types; avoid bare except: |
null | None | Guard with if x is None — never truthiness for 0/"" |
The truthiness trap deserves emphasis: 0, "", [], and {} are falsy. Code like
if items: silently breaks when 0 or empty-string are valid values. Use
is None / len(x) == 0 when the distinction matters — a habit that matters constantly
in AI code, where empty retrieval results are meaningful data, not absence.
The idioms worth adopting
1. Comprehensions and generators. Python’s answer to LINQ is built into the language:
# Transform + filter in one pass
active = [u for u in users if u.is_active]
# Lazy evaluation for large data — like IEnumerable
chunk_tokens = (len(c) for c in chunks)
2. Context managers (with) — the language’s using statement, and everywhere in
AI code (files, HTTP sessions, model handles):
with open("corpus.jsonl", encoding="utf-8") as f:
for line in f:
record = json.loads(line)
3. pathlib over string paths. Path("data") / "docs" / file.name — cross-platform,
composable, no slash bugs. You will be juggling file paths constantly in ingestion code.
4. f-strings and structural unpacking. f"{n:,} tokens" and
first, *rest = items — small things that make code read like prose.
5. Type hints everywhere. Modern Python is typed Python:
def chunk_text(text: str, size: int = 512) -> list[str]:
...
In AI engineering this is not cosmetic: Pydantic (Level 1), function-calling schemas (Level 4), and tool contracts (Level 6) all derive from type hints. Typing is the connective tissue between your code and the model.
The anti-patterns to skip
- Classes for everything. Python’s standard library and the AI ecosystem are function-first. A module of pure functions beats a class with one method.
except:bare catches. SwallowsKeyboardInterruptand hides failures. Catch specific exceptions; let the rest crash loudly.- Mutable default arguments —
def f(items=[])shares the list across calls. A classic bug; useNoneand initialize inside. - Notebook-style code in production. Notebooks are for exploration. AI services in production are modules, packages, and tests — exactly like your C# services.
- Global mutable state for config. Use typed config objects (Pydantic
Settings) loaded from environment — the same discipline asIOptions<T>.
A production-shaped project layout
my-ai-service/
├── pyproject.toml # deps, tool config (ruff, pytest)
├── src/
│ └── my_service/
│ ├── __init__.py
│ ├── config.py # Pydantic settings
│ ├── ingestion.py # document parsing + chunking
│ ├── retrieval.py # embedding + search
│ └── api.py # FastAPI routes
└── tests/
├── test_ingestion.py
└── test_retrieval.py
This is the shape every AI codebase in this roadmap will assume: src layout, typed
modules by responsibility, tests mirroring modules. It is the Python translation of what
you already do in .NET or Node — which is the point.
Hands-on exercise
Build a tiny but typed utility — a text chunker, since you will need one for RAG in Level 5:
- Create a project with
uv init(orpython -m venv), addpytestandpydantic. - Write
chunk_text(text: str, size: int, overlap: int) -> list[str]with type hints. - Handle the edge cases: empty text,
size <= overlap, unicode. - Write pytest tests for each edge case — including one test that fails if someone changes the default argument to a mutable value.
- Run
ruff checkandmypyuntil both are clean.
If this takes you under an hour, your engineering instincts transferred successfully — the rest of Level 1 is vocabulary, not concepts.
Key takeaways
- Learn the tooling (venv/uv, pyproject, ruff, mypy, pytest), not just the syntax — that is where production Python differs from tutorial Python.
- Your existing concepts map cleanly: LINQ → comprehensions, interfaces → Protocols,
records → dataclasses/Pydantic,
using→ context managers. - Adopt: type hints, pathlib, comprehensions, function-first design.
- Skip: classes-for-everything, bare excepts, mutable default args, notebook code in prod.
- Type hints are not style in AI engineering — they are the substrate for validation, structured outputs, and tool contracts in every later level.
Continue your journey
Next mission: Python Type Hints, Pydantic, and Data Validation (coming soon) — or jump ahead to Embeddings: Turning Meaning into Vectors. Full journey: roadmap overview.