Skip to content Skip to sidebar Skip to footer

Using Key Value Pair Assignments For A Dictionary As An Iterator In A For Loop

I just recently came across this cool hack in Python. This: d = {} for i, d[i] in enumerate('abc'): pass >>> d {0: 'a', 1: 'b', 2: 'c'} >>> This assigns k

Solution 1:

You don't have to read CPython code since the behavior is defined in the Python documentation already.

If you read the documentation of the for statement, the target list in a for statement uses rules of a standard assignment:

Each item in turn is assigned to the target list using the standard rules for assignments (see Assignment statements)

And if you read the rules for assignment statements, you can see that each item in the target list of an assignment is assigned to in a left-to-right order:

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

So in the first iteration of your for loop, where a tuple 0, 'a' is generated:

fori, d[i]inenumerate('abc')

An assignment statement equivalent to the following is executed:

i, d[i] = 0, 'a'

which assigns 0 to i first since it's on the left, and then 'a' to d[i], which evaluates to d[0], effectively making d[0] = 'a'.

The same goes for the rest of the iterations.

Solution 2:

@blhsing already explained that it's ordinary left-to-right assignment. I've sometimes done this and similar variations, and I'd like to add why:

  • Brevity. It's slightly shorter, even when your extra variable is only one letter.
  • Speed. It avoids pointless storing and loading of a variable.
  • Cleanliness. Doesn't pollute the namespace with a pointless variable.
  • Laziness. Don't want to have to think of a variable name. That's hard.
  • Education. I like pointing out things that people aren't familiar with :-)
  • Entertainment. Related to the previous point - I like to puzzle people :-D

So to answer your "recommended or not?" and whether it's "considered good practice": I'd say yes, I think it's perfectly fine and even has advantages. The only potential downside I see is that some people might complain about it purely because they're not familiar with it and don't like unfamiliar things.

About the speed aspect: As shown with dis.dis below, everything's the same for both versions except for the additional STORE and LOAD of the extra variable v.

dis.dis('''                       |  dis.dis('''
d = {}                            |  d = {}
for i, d[i] inenumerate('abc'):  |  for i, v inenumerate('abc'):
    pass                          |      d[i] = v
''')                              |  ''')
----------------------------------+-----------------------------------
 0 BUILD_MAP        0             |   0 BUILD_MAP        02 STORE_NAME       0 (d)         |   2 STORE_NAME       0 (d)           
 4 LOAD_NAME        1 (enumerate) |   4 LOAD_NAME        1 (enumerate)   
 6 LOAD_CONST       0 ('abc')     |   6 LOAD_CONST       0 ('abc')       
 8 CALL_FUNCTION    1             |   8 CALL_FUNCTION    110 GET_ITER                       |  10 GET_ITER                         
12 FOR_ITER        12 (to 26)     |  12 FOR_ITER        16 (to 30)       
14 UNPACK_SEQUENCE  2             |  14 UNPACK_SEQUENCE  216 STORE_NAME       2 (i)         |  16 STORE_NAME       2 (i)      
                                  |  18 STORE_NAME       3 (v)
                                  |  20 LOAD_NAME        3 (v)
18 LOAD_NAME        0 (d)         |  22 LOAD_NAME        0 (d)           
20 LOAD_NAME        2 (i)         |  24 LOAD_NAME        2 (i)           
22 STORE_SUBSCR                   |  26 STORE_SUBSCR                     
24 JUMP_ABSOLUTE   12             |  28 JUMP_ABSOLUTE   1226 LOAD_CONST       1 (None)      |  30 LOAD_CONST       1 (None)       
28 RETURN_VALUE                   |  32 RETURN_VALUE

Post a Comment for "Using Key Value Pair Assignments For A Dictionary As An Iterator In A For Loop"