I came across the following interesting construct:
assuming you have a list of lists as follows:
my_list = [[\'captain1\', \'foo1\', \'bar1\', \'foobar1\
As it seems, the pop precedes the assignment of list x as the value and that is why 'captain' does not appear in the values (it is already popped)
No, the order in which it happens is irrelevant. You are mutating the list so you will see the modified list after the pop wherever you use it. Note that in general you probably don't want to do this as you will destroy the original list. Even if that doesn't matter this time its a trap for the unwary in the future.
In both cases the value side is calculated first and then the corresponding key. It's just that in your first case it doesn't matter whereas it does in the second.
You can see this quite easily:
>>> def foo(a): print("foo", a)
...
>>> def bar(a): print("bar", a)
...
>>> { foo(a):bar(a) for a in (1, 2, 3) }
('bar', 1)
('foo', 1)
('bar', 2)
('foo', 2)
('bar', 3)
('foo', 3)
{None: None}
>>>
Note that you should not write code that depends on the values being evaluated first: the behaviour may change in future versions (it was said in some places to have changed in Python 3.5 and later although in fact that appears not to be the case).
A simpler way to do this, which avoids mutating the original data structure:
my_dict = {x[0]: x[1:] for x in my_list}
Or your second example:
my_headers = ['column1', 'column2', 'column3']
my_dict = {x[0]: {k: v for k, v in zip(my_headers, x[1:])} for x in my_list}
To answer the comments: the zip uses the original x
because it is evaluated before the pop
, but it uses the content of the list to construct a new list so any later changes to the list aren't seen in the result. The first comprehension also uses the original x
as the value, but it then mutates the list so the value still sees the original list and hence the mutation.