By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,818 Members | 1,223 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,818 IT Pros & Developers. It's quick & easy.

Function returns a function

P: n/a
Hello,

I want a "function factory" function in python. To do this I made a class like
such (this is for Tkinter, in case your wondering):

class FunctionMaker:
def __init__(self, avar, function, label)
self.var = avar
self.function = function
self.label = label
def __call__(self, e=None):
self.avar.set(self.label)
self.function()

It seems that it would make more sense to make this a function and add it to
the mixin I am writing. But I'm not quite sure how to do this without making
lambdas, which seem a little messy and also look to be on the brink of
deprecation (really not trying to start a lambda pro/con thread here).

Any ideas on how to do this with a regular function, or is the way I've done
it the pythonic choice?

James

--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
Sep 6 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
James Stroud <js*****@mbi.ucla.edu> writes:
Any ideas on how to do this with a regular function, or is the way I've done
it the pythonic choice?


I think you're trying to do something like this:

def FunctionMaker(avar, func, label):
def callback():
avar.set(label)
func()
return callback
Sep 6 '05 #2

P: n/a
Thank you Paul, this makes much more sense.

James

On Tuesday 06 September 2005 02:16 pm, Paul Rubin wrote:
* * def FunctionMaker(avar, func, label):
* * * *def callback():
* * * * * avar.set(label)
* * * * * func()
* * * *return callback


--
James Stroud
UCLA-DOE Institute for Genomics and Proteomics
Box 951570
Los Angeles, CA 90095

http://www.jamesstroud.com/
Sep 6 '05 #3

P: n/a
Paul Rubin wrote:

def FunctionMaker(avar, func, label):
def callback():
avar.set(label)
func()
return callback


I've seen this idiom a lot and I know _what_ it does..... but I can't
work _how_ it does it. How does the name binding work so that "avar" in
the returned function still references the object passed into the
(long-distant!) FunctionMaker() call?

Web pages / turotial ptrs etc gladly accepted.
Sep 7 '05 #4

P: n/a
Thus spake Gregory Bond (gn*@itga.com.au):
Paul Rubin wrote:

def FunctionMaker(avar, func, label):
def callback():
avar.set(label)
func()
return callback


I've seen this idiom a lot and I know _what_ it does.....
but I can't
work _how_ it does it. How does the name binding work so
that "avar" in
the returned function still references the object passed
into the
(long-distant!) FunctionMaker() call?

Web pages / turotial ptrs etc gladly accepted.


The lexical scope within which a function is declared is
made available to the function when it is run. This is done
by storing the values of free variables within the declared
function in the func_closure attribute of the created
function object.

If you want to read more, the keyword you're looking for is
"closure" - a quick search on Google for "python closure"
should satisfy your curiosity handily. There is also a neat
recipe for inspecting the values kept in the func_closure
attribute of function objects directly:

http://aspn.activestate.com/ASPN/Coo.../Recipe/439096


Cheers,
Aldo

--
Aldo Cortesi
al**@nullcube.com
http://www.nullcube.com
Off: (02) 9283 1131
Mob: 0419 492 863

Sep 7 '05 #5

P: n/a
Aldo Cortesi <al**@nullcube.com> writes:
The lexical scope within which a function is declared is
made available to the function when it is run. This is done
by storing the values of free variables within the declared
function in the func_closure attribute of the created
function object.


Actually not quite right:

a = []
for i in range(5):
a.append(lambda: i) # i is free in the lambda
print [f() for f in a]

prints [4,4,4,4,4] instead of [0,1,2,3,4]. The value of i has not
been copied into the closure. Rather, the closure has a cell bound to
the same place that i is bound. So:

for i in range(5):
def f():
j = i # bind a new variable "j" and assign the value from i
return lambda: j # j is free and its value doesn't change
a.append(f())
print [f() for f in a]

prints [0,1,2,3,4]. There's a Pythonic idiom using default args:

a = []
for i in range(5):
a.append(lambda i=i: i) # the "inner" i is free in the lambda
print [f() for f in a]

Closures like may look a little surprising in Python but they're a
standard technique in Scheme. The classic textbook "Structure and
Interpretation of Computer Programming" explains it all. Full text is
online at:

http://mitpress.mit.edu/sicp/
Sep 7 '05 #6

P: n/a
Paul Rubin wrote:
Aldo Cortesi <al**@nullcube.com> writes:

Thanks to Paul and Aldo... one more question on the implementation.

Why is the func_closure a tuple of Cells and not just a tuple of
objects? Why the extra level of indirection?
Sep 7 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.