Общие и локализованные переменные в замыканиях Python
Замыкания в Python ведут себя как бы странно. Рассмотрим следующий фрагмент кода, где я попытался создать список замыканий на основе foo
двумя способами: в bad_closure
затворы строятся "на лету", а в good_closure
замыкания создаются вспомогательной функцией:
def foo(d):
return d + 1
def bad_closure():
''' shares resources implicitly '''
# list of 5 closures
# `i` is shared between all closures
cls = [lambda : foo(i) for i in range(5)]
return cls
def good_closure():
''' no resource sharing '''
def mk_cl(i):
''' helper to make a closure'''
c_ = lambda : foo(i)
return c_
# list of 5 closures
# each closure has its own `i`
cls = [mk_cl(i) for i in range(5)]
return cls
#--- TEST ---
bs = bad_closure()
print([f() for f in bs]) # output: [5, 5, 5, 5, 5]
gs = good_closure()
print([f() for f in gs]) # output: [1, 2, 3, 4, 5]
Результаты поразительно разные. Кажется, что в bad_closure
затворы фиксируются i
каждый, но все они разделяют одно и то же i
который обновляется на каждой итерации (и, наконец, принимает значение 5
)! В отличие от good_closure
, i
Отдельно - как я ожидаю.
Я хотел бы видеть, что происходит за кулисами и почему.