· 2 min readdevsoftware

Python 3.9.0 Is Out, and the Dict Union Operator Is the Small Thing I'm Most Excited About

Python 3.9.0 lands with dict union operators, a new PEG parser, and PEP 585 generic collection types, as Python 3.5 hits end-of-life.

Python 3.9.0 shipped today, right on the annual October cadence we’ve come to expect since the switch to yearly releases. There’s no single headline feature here that reinvents the language, but there’s a pile of quality-of-life improvements that make this a genuinely nice upgrade, plus one change under the hood that matters a lot more than it sounds.

Dict merging finally gets an operator

The one I’ll actually use every day: | and |= for merging dictionaries. Instead of reaching for {**a, **b} or dict(a, **b) — both of which read fine once you know them but are ugly to explain to anyone newer to the language — you can now just write:

merged = dict1 | dict2
dict1 |= dict2

It mirrors how set union already works, so it’s consistent with existing Python idioms rather than inventing a new one. Small thing, but small things you type constantly add up.

A new parser under the hood

The bigger structural change is the switch to a PEG-based parser as the default, replacing the old LL(1) parser that Python had used since roughly forever. Most people won’t notice this at all in day-to-day code — that’s the point. The old parser had accumulated real limitations that made certain grammar changes awkward or impossible to express cleanly. A PEG parser gives the core devs a lot more room to evolve Python’s syntax in future releases without fighting the parser itself. Think of it as paying down technical debt in the compiler so future language features are easier to ship. The old parser is still available as a fallback for this release, presumably as an insurance policy while the new one gets battle-tested in the wild.

Generic types without importing typing

PEP 585 lets you use built-in collection types directly in type hints — list[int] instead of List[int] from the typing module, same for dict, tuple, set, and friends. If you’ve written type hints in the last few years you know the ritual of importing half of typing at the top of every file just to describe basic containers. This collapses a chunk of that boilerplate. It’ll take a while to see this pattern everywhere since plenty of codebases will want to stay compatible with older Python versions for now, but it’s a welcome simplification for anyone who can require 3.9+.

The other shoe: 3.5 is done

Also worth flagging: Python 3.5 reached end-of-life this month, meaning no more security patches from the core team. If you’re maintaining a library or an internal service still pinned to 3.5, this is your prompt to bump the floor. I’d expect a wave of projects over the next few months quietly raising their minimum supported version in response — it’s usually less “urgent migration” and more “we’ve been meaning to do this anyway.”

Nothing in 3.9 should break existing code in any dramatic way, so this reads like a comfortable upgrade for most projects once your dependencies catch up. I’ll be watching how quickly the ecosystem — especially the big frameworks — start recommending 3.9 as a baseline.

Related posts

On this day in other years

Latest on Daily Signal

All posts →