Q:

Lack Understanding of Multi-Variable Assignments Python

I'm new with Python (with Java as a basic). I read Dive Into Python books, in the Chapter 3 I found about Multi-Variable Assignment. Maybe some of you can help me to understand what happen in this code bellow:
>>> params = {1:'a', 2:'b', 3:'c'}
>>> params.items() # To display list of tuples of the form (key, value).
[(1, 'a'), (2, 'b'), (3, 'c')]

>>> [a for b, a in params.items()] #1
['a', 'b', 'c']
>>> [a for a, a in params.items()] #2
['a', 'b', 'c']
>>> [a for a, b in params.items()] #3
[ 1 ,  2 ,  3 ]
>>> [a for b, b in params.items()] #4
[ 3 ,  3 ,  3 ]

What I understand so far is the #1 and #2 has same output, that display the values of tuple. #3 display the key of tuple, and #4 just display the last key from the list of tuples.
I don't understand the use of the variable a and variable b for every case above:

a for b, a ... -> display the values
a for a, a ... -> display the values
a for a, b ... -> display the keys
a for b, b ... -> display the last key

Can anyone elaborate the flow of the loop for every case above?

A:

The list comprehension you use there roughly translate as follows:
[a for b, a in params.items()]

becomes
result = []
for item in params.items():
    b = item[0]
    a = item[1]
    result.append(a)

[a for a, a in params.items()]

becomes
result = []
for item in params.items():
    a = item[0]
    a = item[1] # overwrites previous value of a, hence this yields values, 
                # not keys
    result.append(a)

[a for a, b in params.items()]

becomes
result = []
for item in params.items():
    a = item[0]
    b = item[1]
    result.append(a)

[a for b, b in params.items()]

becomes
result = []
for item in params.items():
    b = item[0]
    b = item[1]
    result.append(a) # note use of a here, which was not assigned

This last one is special. It only worked because you had used the variable a in a previous statement, and the last value that had been assigned to it was 3. If you execute this statement first, you'd get an error.

A:

In all four cases, the names in the tuple are bound to each of the elements in the pair from the sequence in order. The fourth instance is an example of (mis)behavior in Python 2.x; the name is left bound to the last object it had, even outside the LC. This behavior is fixed in 3.x.
>>> [x for x in (1, 2, 3)]
[1, 2, 3]
>>> x
3

3>> [x for x in (1, 2, 3)]
[1, 2, 3]
3>> x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

A:

A tuple is just packing of variables together. You get these pairs when you call 
params.items()

as you have written yourself in the comments. 
To unpack a tuple all you need to do is this:
>>> a, b = (2, 3)
>>> a
2
>>> b
3

The same is done when you use list comprehensions. 
>>> [a for a, b in [(2, 3), (4, 5)]]
[2, 4]

here a takes out the first element of the tuple for every tuple in the list. This is #1 in your case using the params list instead of my short list. 
If you instead write
>>> [b for a, b in [(2, 3), (4, 5)]]
[3, 5]

you get the second element. This corresponds to your #3.
The other two does not really make sense. In #2 you have 
>>> [a for a, a in [(2, 3), (4, 5)]]
[3, 5]
>>> a,a = (2,3)
>>> a
3

which just lets a be first the first and then directly overwrites it with the second argument in each unpacking. You can se this same thing happen with the single tuple.
Last #4 is simply wring. Had you not already used a as a variable this would not have worked since a then doesn't exist. 
>>> [a for b, b in [(2, 3), (4, 5)]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

I hope this answers your questions. 

