python - tutorial - Excepción durante la comprensión de la lista. ¿Se mantienen los resultados intermedios en algún lugar?
qgis introduccion (2)
Cuando se usa try-except en un contexto de bucle for, los comandos ejecutados hasta ahora se realizan obviamente con
a = [1, 2, 3, ''text'', 5]
b = []
try:
for k in range(len(a)):
b.append(a[k] + 4)
except:
print(''Error!'')
print(b)
resultados con
Error!
[5, 6, 7]
Sin embargo, lo mismo no es cierto para las listas de comprensión.
c=[]
try:
c = [a[k] + 4 for k in range(len(a))]
except:
print(''Error!'')
print(c)
Y el resultado es
Error!
[]
¿La lista intermedia, construida antes de que ocurriera la excepción, se mantiene en algún lugar? ¿Es accesible?
Los resultados intermedios de la lista de comprensión se guardan en una pila interna de CPython, y no son accesibles desde las expresiones de Python que forman parte de la lista de comprensión.
Tenga en cuenta que Python ejecuta primero [.....]
, lo que produce un objeto de lista, y solo entonces asigna ese resultado al nombre c
. Si ocurre una excepción dentro de la expresión [....]
, la expresión se termina y en su lugar se inicia el manejo de excepciones. Por lo tanto, su expresión de print(c)
solo puede mostrar el objeto anterior al que estaba vinculado c
, que aquí es un objeto de lista vacía. Podría haber sido cualquier otra cosa:
>>> c = ''Anything else''
>>> try:
... c = [2 // i for i in (1, 0)]
... except ZeroDivisionError:
... pass
...
>>> c
''Anything else''
En su primer ejemplo, no se produce ningún nuevo objeto de lista. En su lugar, manipula (utilizando b.append()
) un objeto de lista existente , por lo que puede ver lo que todas las llamadas b.append()
exitosas b.append()
han hecho.
Veamos el 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...
Como puede ver, la lista de comprensión se traduce en una serie de instrucciones GET_ITER
... JUMP_ABSOLUTE
. La siguiente instrucción STORE_FAST
es la que modifica c
. Si se produce alguna excepción antes de esto, c
no se habrá modificado.