Alright, let’s get into the good stuff. Python 3.8 landed in late 2019, and it brought a couple of features that were genuinely useful, not just the usual under-the-hood optimizations that make you nod politely and then forget about. We’re talking about the Walrus Operator and Positional-Only Parameters. One is a syntactic sugar rush, the other is a quiet but powerful enforcer of API clarity. Let’s break them down.

The Walrus Operator (:=)

First, the one that caused a lot of fuss and some truly terrible aquatic mammal puns: the Walrus Operator, officially known as the Assignment Expression. Its job is simple but profound: it allows you to assign a value to a variable inside an expression. The reason it looks like := is because, well, look at it sideways. It’s a walrus. Let’s move on before I start making seal jokes.

The classic use case is in a while loop where you need to both get a value and check it. The old, clunky way:

# The Old and Busted Way
data = input("Enter something (or 'quit' to exit): ")
while data != 'quit':
    print(f"You entered: {data}")
    data = input("Enter something (or 'quit' to exit): ")

See that ugly repetition of the input() line? It’s a bug waiting to happen. Now, meet the new hotness:

# The New and Walrus-Powered Way
while (data := input("Enter something (or 'quit' to exit): ")) != 'quit':
    print(f"You entered: {data}")

Boom. Clean, concise, and the logic is all in one place. The assignment happens within the condition, and the value of the whole expression is the value that was assigned. This is also a godsend for list comprehensions where you need to call an expensive function and use its result twice.

results = [processed_data for x in raw_data if (processed_data := expensive_transform(x)) is not None]

Without the walrus, you’d have to call expensive_transform(x) twice—once in the condition and once for the result—which is just wasteful.

Pitfall Alert: Don’t get overzealous. The walrus is powerful, but with great power comes great responsibility to not write incomprehensible spaghetti code. Wrapping the assignment expression in parentheses, as I did above, is not just a style choice—it’s often mandatory for clarity and precedence. The PEP enforces this for some cases, and your future self (and code reviewers) will thank you for it.

Positional-Only Parameters (/)

This one is less flashy but arguably more important for library designers. It lets you define parameters that must be passed by position. You can’t use them as keyword arguments. The syntax uses a forward slash / in the function definition to mark the end of the positional-only segment.

“Why on earth would I want to take away flexibility?” I hear you ask. Because sometimes, the flexibility of keyword arguments is a curse. Look at the built-in len() function. What does len(obj=somelist) even mean? It’s nonsense. The parameter is the object. Its name is irrelevant to the function’s purpose. Before /, there was no way to stop users from using the keyword, which just adds noise.

Now we can enforce sanity:

def thrilling_concatenation(a, b, /, separator="-"):
    """First two args are mandatory and positional. Separator can be keyworded."""
    return f"{a}{separator}{b}"

# These are fine
thrilling_concatenation("hello", "world")
thrilling_concatenation("hello", "world", separator="...")

# This will raise a TypeError: thrilling_concatenation() got some positional-only arguments passed as keyword arguments: 'a, b'
thrilling_concatenation(a="hello", b="world")

The parameters a and b before the / are prisoners; they cannot be passed by keyword. The separator parameter after the / is free; it can be passed by position or keyword.

This is all about designing cleaner, more robust APIs. It future-proofs your function. If you have a parameter like x, and you later realize that name is terrible and you want to rename it to input_data, you can do so without breaking every single piece of code that called it with x=5. If it’s positional-only, the name is effectively hidden from the user—it’s an implementation detail.

The Fine Print: You’ll often see / used alongside *, the keyword-only operator. Together, they let you precisely control your function’s signature: which args are positional-only, which can be either, and which must be keyword-only. It’s a thing of beauty for API pedants like me.

def meticulously_designed(arg1, arg2, /, either_arg, *, keyword_only_arg):
    ...  # This function knows what it wants and isn't afraid to ask for it.

Use this power wisely. It’s the key to making your functions communicate their intent as clearly as possible.