How to create a closure
Since loops in Python don't create scopes, you usually need an extra function to create closures. The straightforward way doesn't work:
multipliers = []
for i in range(10):
multipliers.append(lambda x: x * i)
[multipliers[i](2) for i in range(5)]
# [18, 18, 18, 18, 18]
Let's add the extra function:
multiplier_creator = lambda i: lambda x: x * i
for i in range(10):
multipliers.append(multiplier_creator(i))
It works this way, but the code can be clumsy, especially if you need def
, not lambda
:
def multiplier_creator(i):
def multiplier(x):
return x * i
for i in range(10):
return multiplier
multipliers.append(multiplier_creator(i))
To make it slightly more readable, you can write universal function and get partials of it:
multiplier = lambda x, i: x * i
for i in range(10):
multipliers.append(partial(multiplier, i=i))
You can always emulate partial
with custom lambda
, but repr
of partials are generally more readable:
from functools import partial
In : partial(int, base=2)
Out: functools.partial(<class 'int'>, base=2)
In : lambda x: int(x, base=2)
Out: <function __main__.<lambda>>
Fun fact: thanks to the operator
module this particular example can be expressed even more appealing:
from functools import partial
import operator
multipliers = []
for i in range(10):
multipliers.append(partial(operator.mul, i))