anonymous functions/expressions without lambda?

P

Paul Miller

I see lambda is "going away", so I want to use something that will be
around for awhile.

All I want to do is provide an "inline function" as an argument to
another function.

For example, let's say I have a function which binds a key to a function
call. I want to do something "simple" in this function call, and I have
a lot of bindings, so I don't want to have a ton of tiny little
functions scattered around:

def setVarTo1():
foo.var = 1
def setVarTo2():
foo.var = 2

bind('a', setVarTo1)
bind('b', setVarTo2)

Instead, I'd like to do something like this:

bind('a', foo.var = 1)
bind('b', foo.var = 2)

What's the recommended way to do something like this?

Note that the bind function is implemented in "C", and I am embedding
the interpreter.
 
P

Peter Hansen

Paul said:
For example, let's say I have a function which binds a key to a function
call. I want to do something "simple" in this function call, and I have
a lot of bindings, so I don't want to have a ton of tiny little
functions scattered around:

def setVarTo1():
foo.var = 1
def setVarTo2():
foo.var = 2

bind('a', setVarTo1)
bind('b', setVarTo2)

Instead, I'd like to do something like this:

bind('a', foo.var = 1)
bind('b', foo.var = 2)

What's the recommended way to do something like this?

This meets your requirements as stated:

def temp():
foo.var = 1

bind('a', temp)

def temp():
foo.var = 2

bind('b', temp)

del temp


-Peter
 
M

Michael Hoffman

Paul said:
> I see lambda is "going away", so I want to use something that will be
> around for awhile.
>
> All I want to do is provide an "inline function" as an argument to
> another function.

That's what lambda does. But it's going away, you'll have to use def
when it does, unless the language designers come up with something better.
For example, let's say I have a function which binds a key to a function
call. I want to do something "simple" in this function call, and I have
a lot of bindings, so I don't want to have a ton of tiny little
functions scattered around:

def setVarTo1():
foo.var = 1
def setVarTo2():
foo.var = 2

bind('a', setVarTo1)
bind('b', setVarTo2)

If a lot of the bindings are actually setting variables, you could do
something like this:

def attrsetter(obj, name, 1):
def _return_func(value):
return setattr(obj, name, value)

return _return_func
Instead, I'd like to do something like this:

bind('a', foo.var = 1)
bind('b', foo.var = 2)

bind('a', attrsetter(foo, "var", 1))
bind('a', attrsetter(foo, "var", 2))
 
P

Paul Miller

Michael said:
That's what lambda does. But it's going away, you'll have to use def
when it does, unless the language designers come up with something better.

Yeah, I'm using lamda now it works nicely/cleanly.
If a lot of the bindings are actually setting variables, you could do
something like this:

def attrsetter(obj, name, 1):
def _return_func(value):
return setattr(obj, name, value)

return _return_func

bind('a', attrsetter(foo, "var", 1))
bind('a', attrsetter(foo, "var", 2))

Ah, perfect. Thanks!
 
D

Dave Benjamin

Michael said:
That's what lambda does. But it's going away, you'll have to use def
when it does, unless the language designers come up with something better.



If a lot of the bindings are actually setting variables, you could do
something like this:

def attrsetter(obj, name, 1):
def _return_func(value):
return setattr(obj, name, value)

return _return_func

I think you meant to write something like this:

def attrsetter(obj, name, value):
def _return_func():
return setattr(obj, name, value)
return _return_func

Or, if you want to delay binding of the "value" parameter:

def attrsetter(obj, name):
def _return_func(value):
return setattr(obj, name, value)
return _return_func

Cheers,
Dave
 
M

Michael Hoffman

Dave said:
I think you meant to write something like this:

def attrsetter(obj, name, value):
def _return_func():
return setattr(obj, name, value)
return _return_func

Sure did. Sorry.
 
C

Cameron Laird

This meets your requirements as stated:

def temp():
foo.var = 1

bind('a', temp)

def temp():
foo.var = 2

bind('b', temp)

del temp


-Peter

Ewww! *When* is lambda going bye-bye? I apparently
haven't been paying close enough attention. Among other
considerations, I still instruct people to use lambda for
plenty of specific cases.
 
P

Paul Miller

Michael said:
Sure did. Sorry.

You guys have been very helpful!

While on the subject, is there an equivalent for "methodcaller"?

ie. if I want to bind a function which calls a specific method of an
object with a specific parameter?
 
D

Dave Benjamin

Dave said:
You could use a combination of bound methods and the "curry" function
defined in the Python Cookbook:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549

The examples in the discussion do just that.

Also, in the CVS version of Python, there's a new module called
"functional" with a function called "partial" that does the same thing
as far as I can tell. So, in the future, this function will probably be
available in the standard library.

Dave
 
M

Michael Hoffman

Paul said:
While on the subject, is there an equivalent for "methodcaller"?

ie. if I want to bind a function which calls a specific method of an
object with a specific parameter?

def funccaller(func, *args, **kwargs):
def _return_func():
return func(*args, **kwargs)
return _return_func

class Test1(object):
def __init__(self, x):
self.x = x
def method(self, a, b, c):
return self.x + a + b + c

t1 = Test1(42)

funccaller_result = funccaller(t1.method, 3, 4, c=5)
funccaller_result()

And this time I actually tested it, and it works! ;)
 
D

Dave Benjamin

Cameron said:
Ewww! *When* is lambda going bye-bye? I apparently
haven't been paying close enough attention. Among other
considerations, I still instruct people to use lambda for
plenty of specific cases.

Well, IMNSHO, it's an empty threat that's been looming on the horizon
for several years now. ;) Most recently, Guido mentioned his desire to
remove the keyword in his post on Artima, which resulted in a huge debate:

http://www.artima.com/weblogs/viewpost.jsp?thread=98196

Note that in the OP's question, as with Peter's example above, you still
can't do it with lambda alone, since you can't mix expressions with
assignment. Nonetheless, lambda is nice for delaying binding, and
combined with a helper function that sets attributes, it can produce the
most concise solution:

bind('a', lambda: setattr(foo, 'var', 1))
bind('b', lambda: setattr(foo, 'var', 2))

The usual response is that you probably want to make a class anyway, and
use bound methods for this type of stuff. But I find that in GUI/async
programming, often you need a little dab of glue to connect events
between objects, and lambda provides a nice way to avoid
over-abstracting the problem.

We'll see how this all pans out in the next few years. I'm not too fond
of removing features from a language for purely aesthetic reasons, but
lambda's really stuck in a syntactic quandry due to the
statement/expression dichotomy, so I can understand to some extent
Guido's desire to remove it.

Dave
 
P

Paul Miller

Michael said:
def funccaller(func, *args, **kwargs):
def _return_func():
return func(*args, **kwargs)
return _return_func
....

And this time I actually tested it, and it works! ;)

Wow! Amazing. Yer right, it works!

Man, I LOVE this language.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top