What's New in Python 3.8: The Walrus Operator and More

A look at the key features introduced in Python 3.8, including the controversial but powerful assignment expression operator (:=), positional-only arguments, and f-string improvements.

Python 3.8, released in late 2019, brought several new syntax features and improvements to the language. While there were many small enhancements, two features, in particular, stood out: the highly debated assignment expression operator and the introduction of positional-only arguments.

Let's explore the most significant changes in Python 3.8.

The Walrus Operator: Assignment Expressions :=

This is the headline feature of Python 3.8 and the source of much debate. The assignment expression operator, officially known by its PEP 572 but affectionately called the walrus operator because := looks like a pair of eyes and tusks, allows you to assign a value to a variable as part of a larger expression.

It's designed to simplify a common pattern where you need to use a value and also save it for later use, particularly in loops.

The Old Way:

# Reading chunks from a file
while True:
    chunk = f.read(8192)
    if not chunk:
        break
    process(chunk)

The New Way with :=:

while chunk := f.read(8192):
    process(chunk)

This is much more concise. The expression chunk := f.read(8192) both assigns the value of f.read() to chunk and evaluates to that value, which is then used as the condition for the while loop.

It's also useful in list comprehensions where you need to compute a value that is used in both the filtering condition and the expression.

Positional-Only Arguments

Python function arguments can be passed either by position or by keyword. Python 3.8 introduces a new syntax, /, to specify that some function arguments must be specified by position and cannot be used as keyword arguments.

This is useful for library authors who want to be able to rename their internal variable names without breaking client code that might be using the old name as a keyword.

# 'a' and 'b' are positional-only
# 'c' can be positional or keyword
def my_func(a, b, /, c):
    print(a, b, c)

# Valid calls
my_func(1, 2, 3)
my_func(1, 2, c=3)

# Invalid call - 'a' cannot be a keyword argument
# my_func(a=1, b=2, c=3) -> TypeError

You'll now see this syntax in the signatures of many built-in Python functions.

f-strings Support = for Debugging

f-strings get a handy new feature for debugging. You can add an equals sign (=) at the end of an expression, and it will print both the expression and its value.

user = "alice"

# The old way for debugging
print(f"user={user}")

# The new way in Python 3.8
print(f"{user=}") # Output: user='alice'

This is a small but incredibly convenient feature for quick print-statement debugging.

Other Notable Changes

  • importlib.metadata: A new module for reading metadata (like version numbers) from installed packages.
  • Reversible dict: In Python 3.7, dictionaries became insertion-ordered by default. In 3.8, dict is now reversible using reversed().
  • Performance Improvements: As with every new Python release, 3.8 includes many performance optimizations, making the language faster.

Conclusion

Python 3.8 was a solid release that brought some significant new syntax to the language. While the walrus operator took some getting used to for the community, it has proven to be a useful tool for writing more concise code in specific situations. The introduction of positional-only arguments provides more control for API designers, and the f-string debugging feature is a small quality-of-life improvement that developers will appreciate.