Skip to content

Instantly share code, notes, and snippets.

@golgor
Last active June 9, 2020 19:58
Show Gist options
  • Save golgor/3f4a2131e67dfd6656c6e53ac14d437d to your computer and use it in GitHub Desktop.
Save golgor/3f4a2131e67dfd6656c6e53ac14d437d to your computer and use it in GitHub Desktop.
A way to create lambda functions in a loop without having problem with shared free variables.
# Returns a function with n preset when the function handle is created!
def adder(n):
def inner(x):
return x + n
return inner
# Creating preloaded functions
add_1 = adder(1)
add_100 = adder(100)
print(add_1(10)) # 1 + 10 = 11
print(add_100(5)) # 100 + 5 = 105
# Nesting even more!
def subber(n):
def inner(x):
def inner_2(y):
return y*x-n
return inner_2
return inner
# Value to subtract. fn is a closure containting the function inner with value n assigned.
fn = subber(1)
print(f"Free variables of fn: {fn.__code__.co_freevars}")
# with fn as return of subber, i.e. inner, fn returns inner_2. Value to multiply with.
fn2 = fn(2)
print(f"Free variables of fn2: {fn2.__code__.co_freevars}")
# fn2 is called with parameter = 3, which gives 3*2-1 = 5
print(f"Inner_2 returns: {fn2(3)}")
# Hack to go around shared free variables. y=n forces Python to
# evaluate n at creation time for the lambda and store it. Not
# referencing it when the function runs.
adders = []
for n in range(1, 4):
adders.append(lambda x, y=n: x + y)
print(adders[0](10)) # 10 + 1 = 11
print(adders[2](10)) # 10 + 3 = 13
# As y is another parameter, it can be set as well...
print(adders[2](10, 10)) # 10 + 10 = 20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment