Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

python list comprehension double for

vec = [[1,2,3], [4,5,6], [7,8,9]]
print [num for elem in vec for num in elem]      <----- this

>>> [1, 2, 3, 4, 5, 6, 7, 8, 9]

This is tricking me out.
I understand elem is the lists inside of the list from for elem in vic
I don't quite understand the usage of num and for num in elem in the beginning and the end.

How does python interpret this?
What's the order it looks at?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Lets break it down.

A simple list-comprehension:

[x for x in collection]

This is easy to understand if we break it into parts: [A for B in C]

  • A is the item that will be in the resulting list
  • B is each item in the collection C
  • C is the collection itself.

In this way, one could write:

[x.lower() for x in words]

In order to convert all words in a list to lowercase.


It is when we complicate this with another list like so:

[x for y in collection for x in y] # [A for B in C for D in E]

Here, something special happens. We want our final list to include A items, and A items are found inside B items, so we have to tell the list-comprehension that.

  • A is the item that will be in the resulting list
  • B is each item in the collection C
  • C is the collection itself
  • D is each item in the collection E (in this case, also A)
  • E is another collection (in this case, B)

This logic is similar to the normal for loop:

for y in collection:     #      for B in C:
    for x in y:          #          for D in E: (in this case: for A in B)
        # receive x      #              # receive A

To expand on this, and give a great example + explanation, imagine that there is a train.

The train engine (the front) is always going to be there (the result of the list-comprehension)

Then, there are any number of train cars, each train car is in the form: for x in y

A list comprehension could look like this:

[z for b in a for c in b for d in c ... for z in y]

Which would be like having this regular for-loop:

for b in a:
    for c in b:
        for d in c:
            ...
                for z in y:
                    # have z

In other words, instead of going down a line and indenting, in a list-comprehension you just add the next loop on to the end.

To go back to the train analogy:

Engine - Car - Car - Car ... Tail

What is the tail? The tail is a special thing in list-comprehensions. You don't need one, but if you have a tail, the tail is a condition, look at this example:

[line for line in file if not line.startswith('#')] 

This would give you every line in a file as long as the line didn't start with a hashtag (#), others are just skipped.

The trick to using the "tail" of the train is that it is checked for True/False at the same time as you have your final 'Engine' or 'result' from all the loops, the above example in a regular for-loop would look like this:

for line in file:
    if not line.startswith('#'):
        # have line

please note: Though in my analogy of a train there is only a 'tail' at the end of the train, the condition or 'tail' can be after every 'car' or loop...

for example:

>>> z = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
>>> [x for y in z if sum(y)>10 for x in y if x < 10]
[5, 6, 7, 8, 9]

In regular for-loop:

>>> for y in z:
    if sum(y)>10:
        for x in y:
            if x < 10:
                print x

5
6
7
8
9

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...