Gyaan

Walrus Operator and Modern Features

intermediate walrus-operator pattern-matching modern-python 3.8+

Python keeps evolving. Let’s look at the most useful features added in recent versions (3.8 through 3.12) that we’ll actually use in day-to-day code.

Walrus Operator := (Python 3.8)

The walrus operator lets us assign and use a value in the same expression. It’s called “walrus” because := looks like a walrus turned sideways.

Without it, we often compute something, check it, then use it — requiring extra lines:

# Before — compute, then check
line = input("Enter: ")
while line != "quit":
    print(f"You said: {line}")
    line = input("Enter: ")

# With walrus — assign and check in one shot
while (line := input("Enter: ")) != "quit":
    print(f"You said: {line}")

It’s especially handy in list comprehensions and conditions:

# Filter and transform in one pass
results = [clean for name in names if (clean := name.strip()) != ""]

# Avoid computing a regex match twice
import re
if (match := re.search(r"\d+", text)):
    print(f"Found number: {match.group()}")

The rule is: don’t overuse it. If it makes the line harder to read, stick with two lines.

Positional-Only Parameters / (Python 3.8)

We can now force certain parameters to be positional-only using /:

def greet(name, /, greeting="Hello"):
    print(f"{greeting}, {name}!")

greet("Manish")                  # works
greet("Manish", greeting="Hi")   # works
greet(name="Manish")             # TypeError — name is positional-only

Everything before / must be passed by position. This is useful for library authors who want to keep parameter names as implementation details.

Structural Pattern Matching match/case (Python 3.10)

This is Python’s version of switch/case, but way more powerful. It matches patterns, not just values.

def handle_command(command):
    match command.split():
        case ["quit"]:
            print("Goodbye!")
        case ["go", direction]:
            print(f"Going {direction}")
        case ["pick", "up", item]:
            print(f"Picked up {item}")
        case _:
            print("Unknown command")

handle_command("go north")     # Going north
handle_command("pick up sword") # Picked up sword

We can match types, destructure objects, and use guards:

def describe(value):
    match value:
        case int(n) if n > 0:
            print(f"Positive integer: {n}")
        case str(s) if len(s) > 5:
            print(f"Long string: {s}")
        case [first, *rest]:
            print(f"List starting with {first}")
        case {"name": name, "age": age}:
            print(f"{name} is {age}")
        case _:
            print("Something else")

The _ is the wildcard — it matches anything, like default in other languages.

Union Type X | Y (Python 3.10)

Instead of Union[str, int] from the typing module, we can now use the pipe operator:

# Before (3.5-3.9)
from typing import Union, Optional
def parse(value: Union[str, int]) -> str: ...
def find(id: int) -> Optional[str]: ...

# After (3.10+)
def parse(value: str | int) -> str: ...
def find(id: int) -> str | None: ...

Much cleaner. Works in isinstance() too:

isinstance(42, int | str)  # True

Exception Groups and except* (Python 3.11)

When multiple things fail at once (like in asyncio.gather()), we can now handle groups of exceptions:

try:
    raise ExceptionGroup("errors", [
        ValueError("bad value"),
        TypeError("wrong type"),
    ])
except* ValueError as eg:
    print(f"Value errors: {eg.exceptions}")
except* TypeError as eg:
    print(f"Type errors: {eg.exceptions}")

The except* syntax matches specific exception types within the group. Multiple except* blocks can each handle different parts of the same group.

F-string Improvements (Python 3.12)

F-strings got more flexible — we can now nest quotes and use expressions that were previously forbidden:

# Python 3.12 — nested quotes and complex expressions
names = ["Alice", "Bob"]
print(f"Users: {", ".join(names)}")  # was a SyntaxError before 3.12

# Multiline expressions inside f-strings
print(f"Result: {
    sum(x**2 for x in range(10))
}")

type Statement (Python 3.12)

A cleaner way to define type aliases:

# Before
from typing import TypeAlias
UserID: TypeAlias = int

# Python 3.12
type UserID = int
type Matrix = list[list[float]]
type Handler = Callable[[Request], Response]

In simple language, Python’s modern features make our code shorter and more expressive. The walrus operator saves lines, pattern matching replaces clunky if/elif chains, and the pipe syntax makes type hints readable. We don’t need all of them, but knowing they exist helps us write cleaner code.