pythonpython-assignment-expression

For-loop with the walrus operator inside the range


Why are the negative k values being printed as the original value, but when we enter the positive realm, it gets strange?

In:

def j(k):
    for i in range(i:=k):
        i+=i
    print(i)
for i in [-5,-4,-3,-2,-1,0,1,2,3,4,5]:
    j(i)

Out:

-5
-4
-3
-2
-1
0
0
2
4
6
8

Solution

  • This has nothing to do with the walrus operator; it might actually be easier to understand without it.

    def j(k):
        i = k
        for i in range(k):
            i+=i
        print(i)
    for i in [-5,-4,-3,-2,-1,0,1,2,3,4,5]:
        j(i)
    

    The negative-numbers weirdness occurs because for any nonpositive k, range(k) is empty. That means the for loop gets skipped, so j(k) just prints k.

    For positive k, the behavior occurs because the i in the for statement is the same as the i you declared outside the loop. Every iteration of the for-loop reassigns i to the next value in the range, overwriting any previous changes, so the only iteration that matters is the last one.

    In the last iteration, the for-loop itself assigns i=k-1 since that's the last value in the range. Then, i+=i doubles that, so i==2*(k-1). Then, the loop exits, but i keeps that value and gets printed.

    In effect, your code is equivalent to the following:

    def j(k):
        if k <= 0:
            print(k)
        else:
            print(2 * (k - 1))
    

    Which makes the output for [-5,-4,-3,-2,-1,0,1,2,3,4,5] -5, -4, -3, -2, -1, 0, 0, 2, 4, 6, 8.