Python walrus operator fails within range

Viewed 141

Why can I use something like

import numpy as np

print( (g := np.arange(256)**2) / np.max(g) )

but the following fails?

foo = list(range(256))
for i in range( (l := len(foo)) // 16 + 0 if l%16 == 0 else 1 ):
    print(i)
Traceback (most recent call last):
  File "test.py", line 8, in <module>
    for i in range( (l := len(foo)) // 16 + 0 if l%16 == 0 else 1 ):
NameError: name 'l' is not defined
1 Answers

In an argument list, expressions are evaluated from left to right, so in:

plt.plot( range( len( (Y := foo) )), Y )

the first argument range( len( (Y := foo) )) is evaluated before the second argument Y, and therefore Y is defined with foo before Y is referenced as a second argument.

However, in a conditional expression, the expression in the if clause is evaluated before either of the outputting expressions is evaluated, so in:

(l := len(foo)) // 16 + 0 if l%16 == 0 else 1

l%16 == 0 is evaluated first, and since l isn't yet defined at that point, it raises the said NameError.

You can instead define l in the if clause first if that is indeed the logic you want:

for i in range( l // 16 + 0 if (l := len(foo))%16 == 0 else 1 ):
Related