Reputation: 6127
I'm doing a complicated hack in Python, it's a problem when you mix for+lambda+*args (don't do this at home kids), the boring details can be omited, the unique solution I found to resolve the problem is to pass the lambda object into the self lambda in this way:
for ...
lambda x=x, *y: foo(x, y, <selflambda>)
It's possible?, thanks a lot.
Upvotes: 3
Views: 876
Reputation: 76715
I don't understand why you want to do this with lambda
.
lambda
: creates a function object that does not have a name
def
: creates a function object that does have a name
a name: very useful for calling yourself
for ...
def selflambda(x=x, *y):
return foo(x, y, selflambda)
...
Doesn't this do exactly what you requested? I even called it selflambda
. If it doesn't do what you want, would you please explain why it doesn't?
EDIT: Okay, Jason Orendorff has pointed out that this won't work, because each time through the loop, the name selflambda
will be rebound to a new function, so all the function objects will try to call the newest version of the function. I'll leave this up for the educational value, not because it is a good answer.
Upvotes: 0
Reputation: 45116
The easiest way is to write a separate function to create the lambda.
def mkfun(foo, x):
f = lambda x=x, *y: foo(x, y, f)
return f
for ...:
...mkfun(foo, x)...
This works just like gnibbler's suggestion but can be used in a for loop.
EDIT: I wasn't joking. It really works!
def foo(x, y, bar):
print x
if y:
bar() # call the lambda. it should just print x again.
# --- gnibbler's answer
funs = []
for x in range(5):
bar=lambda x=x, *y: foo(x, y, bar) # What does bar refer to?
funs.append(bar)
funs[2](2, True) # prints 2 4 -- oops! Where did the 4 come from?
# --- this answer
def mkfun(x, foo):
bar = lambda x=x, *y: foo(x, y, bar) # different bar variable each time
return bar
funs = []
for x in range(5):
funs.append(mkfun(x, foo))
funs[2](2, True) # prints 2 2
Upvotes: 0
Reputation: 45116
You are looking for a fixed-point combinator, like the Z combinator, for which Wikipedia gives this Python implementation:
Z = lambda f: (lambda x: f(lambda *args: x(x)(*args)))(lambda x: f(lambda *args: x(x)(*args)))
Z takes one argument, a function describing the function you want, and builds and returns that function.
The function you're looking to build is:
Z(lambda f: lambda x=x, *y: foo(x, y, f))
Upvotes: 8
Reputation: 4315
While your question is genuinely weird, try something like:
>>> import functools
>>> f = lambda selflambda, x=x, *y: foo(x, y, selflambda)
>>> f = functools.partial(f, f)
Upvotes: 4
Reputation: 304255
If you want to refer to it, you'll have to give it a name
bar=lambda x=x, *y: foo(x, y, bar)
such is the way of the snake
Upvotes: 0