Can you use in-place operators with the Python 3.8 "Walrus" operator?

Viewed 646

In Python 3.8, the Walrus operator was introduced, allowing assignment as an expression.

This means we can replace these 2 statements

a = 2
print(a)

with

print(a := 2)

However, Python also has "in-place" assignment with operators where, for example, a = a * 3 is equivalent to a *= 3

Is there any way to use "in-place" operator assignment, in combination with Walrus assignment?

For the following code

a *= 3
print(a)

To re-create this with Walrus assignment, it seems you must do

print(a := a * 3)

Both of these attempts raise a SyntaxError

print(a :*= 3)
print(a *:= 3)
3 Answers

No, augmented assignment (what you call "in-place" assignment, which doesn't always occur) is not supported with Python's Walrus operator, as stated in the specification PEP-0572.

The "equivalent" (quotes with emphasis) of

y ?= x

where ? is a supported symbol (e.g. +, -, *, >>, <<,...) is

(y := y ? x)

This is unfortunate from the perspective of programmers coming from C/C++ that have learned to appreciate that assignment expressions such as (which in C/C++ are valid not only as stand-alone statements as in Python, but as the loop condition or just about anywhere where a value can be substituted, assuming appropriate types)

(y ?= x)

which can make code more concise and perhaps more efficient by telling the compiler to do in-place assignment if they can (in C/C++, p++ and ++p -- analagous to p += 1 -- which both increment p in-place, are also idiomatic in loop conditions, stand-alone statements or just about anywhere where the (before-increment) value of p or its incremented value is needed).

Still, the Walrus operator at least helps make code more concise and readable in some situations.

def logb2(n: int):
    "return the (bit) position of the most significant bit of n"
    result = 0
    while (n := n >> 1):
        result += 1
    return result 

which I prefer over something like

def logb2(n: int):
    result = 0
    while True: 
        n >>= 1 
        if n:
            result += 1 
        else:
            return result

On my hardware and software, timeit.timeit shows that they take about the same amount of time, with the latter performing slightly (though negligibly, negligibly) better, despite the former requiring about 3 less bytecode instructions (less bytecote instructions does not necessarily imply more efficient of course).

There are many good use cases of the Walrus operator though in my view it is most beneficial in situations where it improves readability.

Support for what you (we) are after CAN be implemented in Python, but I don't see this happening anytime soon, if ever (which, well, is not such a bad thing).

You can't use in-place operators with the walrus operator.

Explanation :

The walrus operator assign a value to a new variable and return its value.

In-place operators are shortcuts to apply operators to an existing variable and update the variable. In-place operators would have no meaning for a new variable. They raise an error if they are applied to a variable that is not assigned yet.

Therefore combining in-place and walrus has no use case.

Edit: A more practical explanation :

what would be the meaning of a:+=1 ? if a doesn't exists, to what value 1 would be added ? what would be the final value of a ?

for reference :

a:=8 #means : assign 8 to a and "return" a 
a+=1 #means : a = a +1 and it raises an exception if a doesn't exists

You need to define a first:

print((a := 2)*3)

6

Related