....: print a,'----'
....: a.append(1)
....: import time
....: time.sleep(1)
....: p() //default arg changed preserved in inner call again , but not outside
use closure implemt local static variable in python
def make_printer(msg):
a = 'local static var'
def printer():
st = a
print msg
return printer
printer = make_printer('Foo!')
printer()
def static_var(varname, value):
def decorate(func):
setattr(func, varname, value)
return func
return decorate
Then use the code like this:
@static_var("counter", 0)
def foo():
foo.counter += 1
print "Counter is %d" % foo.counter
def makefoo():
x = 0
def foo():
x += 1 // this won't work instead you should use nonlocal x (or b =x ; b++ , but then x can not be change)
print x
return foo
def outer(x):
def intermediate(y):
free = 'free'
def inner(z):
return '%s %s %s %s' % (x, y, free, z)
return inner
return intermediate
outer('I')('am')('variable')
inter = outer('I')
inter.func_closure
inter.func_closure[0].cell_conten
Closures are functions that inherit variables from their enclosing environment
A closure occurs when a function has access to a local variable from an enclosing scope that has finished its execution.
In Python 3, func_closure
is now called __closure__
or use class .__call__() // the same time use singleton
http://www.codedata.com.tw/java/understanding-lambda-closure-3-python-support/
def foo():
print 'Foo!'
Simple enough. A function foo
prints the string ‘Foo!’.
Let’s play with the scoping of Python and figure out what happens when we create a lambda that calls foo()
.
foo = lambda: foo() // foo no longer exist , replaced by this, call this will recursive
What do you think will happen when we call it?
>>> foo()
Traceback (most recent call last):
but if we do this:
b = foo
foo = otherfunc
b()
worked !!!
The Solution
You can force the caller’s scope into a closure, sort of, using a Python keyword. It looks a little funny at first, but consider the code below.
foo = lambda foo=foo: foo()
The reason is that closures (lambdas or otherwise) close over names, not values. When you define lambda x: test_fun(n, x)
, the n is not evaluated, because it is inside the function. It is evaluated when the function is called, at which time the value that is there is the last value from the loop.
You say at the beginning that you want to "use closures to eliminate a variable from a function signature", but you can't really do that. Variables inside the function body will not be evaluated when the function is defined. In order to get the function to take a "snapshot" of the variable as it exists at function-definition time, you must pass the variable as an argument to the function. The usual way to do this is to give the function an argument whose default value is the variable from the outer scope. Look at the difference between these two examples:
>>> stuff = [lambda x: n+x for n in [1, 2, 3]]
>>> for f in stuff:
... print f(1)
4
4
4
>>> stuff = [lambda x, n=n: n+x for n in [1, 2, 3]]
>>> for f in stuff:
... print f(1)
2
3
4
In the second example, passing n
as an argument to the function "locks in" the current value of n to that function. You have to do something like this if you want to lock in the value in this way. (If it didn't work this way, things like global variables wouldn't work at all; it's essential that free variables be looked up at the time of use.)