Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does this Python statement mean?

Tags:

python

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?

like image 211
user541686 Avatar asked Sep 30 '12 08:09

user541686


People also ask

What does indentation mean in Python?

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.


1 Answers

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
like image 75
Martijn Pieters Avatar answered Sep 22 '22 01:09

Martijn Pieters