ZB Field Notes

Learning Python as a Java Dev: My On-Ramp to AI

Learning Python as a Java Dev: My On-Ramp to AI

Why Python, and why now

I’ve spent most of my career on the JVM — secure, event-driven Java and Spring Boot services, Kafka, the kind of systems regulated banking runs on. Python was always the other language: I could read it, copy a snippet, make it run. I never actually wrote it.

What changed is where the interesting work moved. The AI world — agents, model SDKs, the whole tooling layer — is Python-first. I could keep bouncing off half-understood snippets, or I could sit down and build the muscle properly. I chose the second option, and I chose to build myself a course rather than watch one: python-intro-0-to-hero, ten runnable lessons from variables to a small capstone.

The trick: map every concept back to Java

Most “learn Python” material for an experienced engineer makes the same mistake — it starts at this is a variable. I don’t need that. I need the diff: what is actually different from what I already do on the JVM. So I wrote every lesson as a translation. Here’s the Java I’d reach for, here’s the Python that replaces it.

// Java
String msg = String.format("%s is %d years old", name, age);
// Python
msg = f"{name} is {age} years old"

My existing mental model stopped being baggage and became the scaffolding. Every new idea had a hook to hang on, which is the whole reason the course moved fast.

Two-column table mapping Java syntax on the left to the equivalent Python on the right: variable declaration, string formatting, streams, records, and object construction.
Five everyday patterns in the language I knew and the language I was learning. The point was never the syntax — it’s that each row already had a home in my head.

The resets that actually mattered

A handful of these genuinely rewired how I think, coming from a statically typed world:

  • Types are optional — and mutable. age = 30 then age = "thirty" is perfectly legal. In Java that’s a compile error; in Python it just… runs. Liberating and slightly terrifying at the same time.
  • f-strings beat String.format. Dropping variables straight inside { } is the feature I miss most the moment I go back to Java.
  • Comprehensions are Streams without the ceremony. [n*n for n in nums if n > 0] is one line — no .stream(), no .collect(toList()).
  • @dataclass is a record. It generates __init__, __eq__ and a readable __str__ for you — the exact deal Java records made in 16.
  • No new, and self is this you spell out. The constructor is __init__; the operators you override via equals() and toString() in Java are Python’s dunder methods (__eq__, __str__).

The capstone: a tiny bank system

Lesson 10 pulls everything into one file — deliberately in a domain I know cold. An Account, a SavingsAccount subclass, a custom exception, a @dataclass transaction record, a @property for the derived balance, and a comprehension over the ledger. Familiar problem, unfamiliar language — which is exactly where the learning happens.

class SavingsAccount(Account):
    def __init__(self, owner, balance=0.0, rate=0.05):
        super().__init__(owner, balance)      # Java: super(owner, balance);
        self.rate = rate

    def add_interest(self):
        self.deposit(self.balance * self.rate)  # reuse the inherited method

Show me that block cold a month earlier and I’d have filed it under “scripting toy”. Now I read it as an inheritance hierarchy calling a reused parent method — the same shape I’d write in Java, minus the noise.

Then I built the tutor that taught me

Here’s where the Python loop closed back onto the actual goal. The same repo carries a second thing: a learn-by-building tutor agent — a minimal Python program that loops a model, lets it call a run_code tool, feeds the real stdout back, and keeps going. No SDK, on purpose, so the mechanics stay visible.

And it maps cleanly onto the world I already live in. An LLM agent is just a loop around a stateful model that can call tools — which is a controller taking a request, calling downstream services mid-request, then answering. My Spring instincts transferred wholesale; only the vocabulary changed.

Dark two-column table mapping the tutor agent's parts (outer input loop, inner model-plus-tools loop, system prompt, run_code tool, dispatch function) to Spring Boot concepts (controller, request handler, service-layer policy, outbound adapter, router).
The tutor agent read through Spring-tinted glasses. Once the loop looked like a controller calling services, Python stopped being the subject and became the tool.
The goal was never to become a Python expert overnight. It was to make Python a language I build in — so the AI world stops being read-only.

That’s the whole arc: from int age = 30; to a working bank system to a tiny agent that runs code and reacts to its own output. Ten lessons, one repo, every idea anchored to something I already knew. If you’re a JVM engineer eyeing the AI space, don’t start from zero — start from Java and translate. The repo is public if you want the same on-ramp.