Исключение во время понимания списка. Сохраняются ли промежуточные результаты в любом месте?
При использовании try-except в контексте цикла for команды, выполненные до сих пор, очевидно, выполняются с помощью
a = [1, 2, 3, 'text', 5]
b = []
try:
for k in range(len(a)):
b.append(a[k] + 4)
except:
print('Error!')
print(b)
результат с
Error!
[5, 6, 7]
Тем не менее, это не относится к пониманию списков
c=[]
try:
c = [a[k] + 4 for k in range(len(a))]
except:
print('Error!')
print(c)
И результат
Error!
[]
Является ли промежуточным списком, созданным до возникновения исключения, хранится где угодно? Доступен ли он?
Ответы
Ответ 1
Промежуточные результаты по составлению списка хранятся во внутреннем стеке CPython и не доступны из выражений Python, которые являются частью понимания списка.
Обратите внимание, что Python выполняет [.....]
первый, который создает объект списка, и только , а затем присваивает этот результат имени c
. Если в выражении [....]
возникает исключение, выражение прекращается, и вместо этого обрабатывается обработка исключений. Таким образом, выражение print(c)
может показывать только предыдущий объект, к которому привязан c
, который представляет собой пустой объект списка. Это могло быть что-то еще:
>>> c = 'Anything else'
>>> try:
... c = [2 // i for i in (1, 0)]
... except ZeroDivisionError:
... pass
...
>>> c
'Anything else'
В первом примере не создается новый объект списка. Вместо этого вы управляете (используя b.append()
) существующий объект списка, поэтому вы можете видеть, что сделали с ним все успешные вызовы b.append()
.
Ответ 2
Посмотрим на байт-код:
>>> 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...
Как вы можете видеть, понимание списка переводится в ряд инструкций GET_ITER
... JUMP_ABSOLUTE
. Следующая команда STORE_FAST
- это та, которая изменяет c
. Если перед ним возникает какое-либо исключение, c
не будет изменено.