What's New in Python 3.9?

A look at the major new features coming in Python 3.9, including the new dictionary merge operators, more flexible type hinting, and the new zoneinfo module for timezone support.

As the Python development community prepares for the final release of Python 3.9 in October 2020, the preview releases have given us a clear picture of the new features and improvements to expect. While not as packed with major syntax changes as Python 3.8, version 3.9 brings some highly anticipated quality-of-life improvements, particularly for working with dictionaries and type hints.

Let's explore the most significant new features in Python 3.9.

1. Dictionary Merge & Update Operators

This is the most talked-about feature in Python 3.9. For years, merging two dictionaries has been a bit clumsy. Python 3.9 introduces two new operators to make this much cleaner: the merge operator (|) and the update operator (|=).

The Old Way:

d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}

# To merge, you might do this:
d3 = d1.copy()
d3.update(d2)

# Or this (since Python 3.5):
d3 = {**d1, **d2}

The New Way with |:

The | operator creates a new dictionary by merging the two operands.

d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}

d3 = d1 | d2
print(d3) # Output: {'a': 1, 'b': 3, 'c': 4}

If a key exists in both dictionaries, the value from the right-hand operand wins.

The New Way with |=:

The |= operator updates a dictionary in-place.

d1 |= d2
print(d1) # Output: {'a': 1, 'b': 3, 'c': 4}

This is a clean, readable, and highly welcome addition to the language.

2. More Flexible Type Hinting

Python 3.9 makes type hinting more convenient by allowing you to use built-in collection types (like list and dict) as generic types directly in type annotations. Previously, you had to import the capitalized versions (List, Dict) from the typing module.

The Old Way:

from typing import List, Dict

def process_names(names: List[str]) -> None:
    # ...

The New Way:

No import from typing is needed for these common types.

def process_names(names: list[str]) -> None:
    # ...

This change (specified in PEP 585) makes type hints cleaner and easier to write.

3. The zoneinfo Module

Dealing with timezones in Python has historically required third-party libraries like pytz. Python 3.9 introduces the new zoneinfo module, which brings support for the IANA time zone database directly into the standard library.

from datetime import datetime
from zoneinfo import ZoneInfo

# Create a timezone-aware datetime object
dt = datetime(2020, 8, 17, 12, tzinfo=ZoneInfo("America/Los_Angeles"))

print(dt)
print(dt.tzname()) # Output: PDT

This is a major step forward for handling timezones in a standardized way.

4. New String Methods: removeprefix() and removesuffix()

Two convenient new methods have been added to the str object for removing a prefix or a suffix from a string.

The Old Way:

if my_string.startswith('https'):
    my_string = my_string[len('https'):]

The New Way:

my_string = my_string.removeprefix('https')

This is a small but useful addition that makes code more readable and less error-prone.

Conclusion

Python 3.9 is a release focused on developer quality of life. The new dictionary operators provide a long-awaited, clean syntax for a common operation, while the improvements to type hinting and the addition of the zoneinfo module continue the trend of making Python's standard library more powerful and convenient. These changes help developers write cleaner, more expressive, and more robust code.