The Python Oracle

Exception during list comprehension. Are intermediate results kept anywhere?

This video explains
Exception during list comprehension. Are intermediate results kept anywhere?

--

Become part of the top 3% of the developers by applying to Toptal
https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Peaceful Mind

--

Chapters
00:00 Question
00:52 Accepted answer (Score 26)
02:05 Answer 2 (Score 11)
03:03 Thank you

--

Full question
https://stackoverflow.com/questions/3823...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #listcomprehension

#avk47



ACCEPTED ANSWER

Score 26


The list comprehension intermediate results are kept on an internal CPython stack, and are not accessible from the Python expressions that are part of the list comprehension.

Note that Python executes the [.....] first, which produces a list object, and only then assigns that result to the name c. If an exception occurs within the [....] expression, the expression is terminated and exception handling kicks in instead. Your print(c) expression thus can only ever show the previous object that c was bound to, which here is an empty list object. It could have been anything else:

>>> c = 'Anything else'
>>> try:
...     c = [2 // i for i in (1, 0)]
... except ZeroDivisionError:
...     pass
...
>>> c
'Anything else'

In your first example, no new list object is produced. You instead manipulate (using b.append()) an existing list object, which is why you can see what all successful b.append() calls have done to it.




ANSWER 2

Score 11


Let's look at the bytecode:

>>> def example():
...     c=[]
...     try:
...         c = [a[k] + 4 for k in range(len(a))]
...     except:
...         print('Error!')
...     print(c)
... 
>>> import dis
>>> dis.dis(example)

--- removed some instructions       

             27 GET_ITER            
        >>   28 FOR_ITER                20 (to 51)
             31 STORE_FAST               1 (k)
             34 LOAD_GLOBAL              2 (a)
             37 LOAD_FAST                1 (k)
             40 BINARY_SUBSCR       
             41 LOAD_CONST               1 (4)
             44 BINARY_ADD          
             45 LIST_APPEND              2
             48 JUMP_ABSOLUTE           28
        >>   51 STORE_FAST               0 (c)

 --- more instructions...

As you can see, the list comprehension is translated to a series of instructions GET_ITER...JUMP_ABSOLUTE. The next instruction STORE_FAST is the one that modifies c. If any exception occurs before it, c will not have been modified.