I'm writing a parser, and in the process of debugging it, I found that apparently, this is legal Python:
for [] in [[]]: print 0
and so is this (!):
for [][:] in [[]]: print 0
I don't blame the parser for getting confused... I'm having trouble figuring out how to interpret it!
What exactly does this statement mean?
Indentation refers to the spaces at the beginning of a code line. Where in other programming languages the indentation in code is for readability only, the indentation in Python is very important. Python uses indentation to indicate a block of code.
In terms of execution: nothing.
The for
loop itself loops over an empty list, so no iterations will take place.
And that's a good thing, because the for []
means: assign each entry in the loop to 0 variables. The latter part is probably what is puzzling you.
The statement is legal because the target token token_list
allows you to assign the values in a sequence to an equally large sequence of variable names; we call this tuple unpacking. The following are more useful examples of target lists, in assignment and deletion:
(a, b, c) = range(3)
del a, b, c
You can do the same in a for
loop:
nested = [[1,2,3], [4,5,6]]
for a, b, c in nested:
print nested
You can use both tuples and lists for the target_list
token, this is legal too:
[a, b] = (1, 2)
However, in Python, a list can be empty. Thus, the following is legal, however non-sensical:
[] = []
and finally, so is this:
nested_empty = [[], [], []]
for [] in nested_empty:
pass
More fun with target lists:
[][:] = [1, 2, 3]
Now the left-hand side is using a slice in the assignment. From the documentation:
If the target is a slicing: The primary expression in the reference is evaluated. It should yield a mutable sequence object (such as a list). The assigned object should be a sequence object of the same type. Next, the lower and upper bound expressions are evaluated, insofar they are present; defaults are zero and the sequence’s length. The bounds should evaluate to (small) integers. If either bound is negative, the sequence’s length is added to it. The resulting bounds are clipped to lie between zero and the sequence’s length, inclusive. Finally, the sequence object is asked to replace the slice with the items of the assigned sequence. The length of the slice may be different from the length of the assigned sequence, thus changing the length of the target sequence, if the object allows it.
So here we are no longer using tuple unpacking; instead we replace a section of the left-hand list with the right-hand list. But because in our example the left-hand list is an anonymous list literal, the resulting altered list is lost again.
But because such an assignment is also legal in a for loop, the following is legal syntax, albeit rather non-sensical:
for [][:] in [range(i) for i in range(10)]: print 0
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With