In python functions its perfectly legal to reference variables from enclosing scopes. These variables refer to whatever value they posses at the time the function is called. So, for instance
x = 1 # unused
def foo(y):
return x+y
x=10
print(foo(1)) # prints 11
x=11
print(foo(1)) # prints 12
is it possible to make the variable x
be frozen to whatever the value of x
was at creation time? That is, I want the x
in foo
to bind to the value of the outer x
rather than its name. Basically the behavior I want is
x = 1
def foo(y):
return 1+y # I'd rather not hard code the value of x here
x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2
I currently have a working solution, but It's not very readable, I think there might be a better solution (a decorator perhaps?)
my solution
x = 1
def wrapper():
local_x = x
def foo(y):
return local_x+y
return foo
foo = wrapper()
x=10
print(foo(1)) # prints 2
x=11
print(foo(1)) # prints 2
Use functools.partial to apply the first argument and get a new function accepting one argument. I chose not to decorate the add function, as it is very general and useful elsewhere.
from functools import partial
from operator import add # does same thing as your foo
x = 1
foo = partial(add, x)
print(foo(1)) # prints 2
x = 11
print(foo(1)) # prints 2
In keeping with your original solution, you could also do something like.
def wrapper(localx):
def foo(y):
return localx + y
return foo
foo2 = wrapper(x)
print(foo2(1)) # prints 12
Note that now the dependency on a global is cut and you could even pass a literal value to wrapper
(e.g. foo3 = wrapper(5)
).