2

I'd like to assign a variable to the scope of a lambda that is called several times. Each time with a new instance of the variable. How do I do that?

f = lambda x: x + var.x - var.y

# Code needed here to prepare f with a new var

result = f(10)

In this case it's var I'd like to replace for each invocation without making it a second argument.

9
  • 2
    don't use a lambda, use a regular function, you shouldn't feel the need to use lambdas whenever possible Commented May 15, 2013 at 8:05
  • 2
    In general, if a lambda is complex enough that you have to ask how to contort it to accomplish a task, just use a regular 'def' function. It will result it more readable, maintainable code. Commented May 15, 2013 at 8:07
  • @jamylak I agree. But lambda or regular function, I'm not sure how the OP wants to accomplish what he's asking. How do you change something in the scope of a function, without using an argument? Commented May 15, 2013 at 8:09
  • You can replace the lambda with a regular function if that helps. I just need to somehow manipulate the functions local variables/closure. Commented May 15, 2013 at 8:11
  • 1
    possible duplicate of How to modify the local namespace in python or How to dynamically modify a function's local namespace? @JonathonReinhart there are a few ways but no clean ones as seen in those links Commented May 15, 2013 at 8:14

4 Answers 4

9

Variables undefined in the scope of a lambda are resolved from the calling scope at the point where it's called.

A slightly simpler example...

>>> y = 1
>>> f = lambda x: x + y
>>> f(1)
2
>>> y = 2
>>> f(1)
3

...so you just need to set var in the calling scope before calling your lambda, although this is more commonly used in cases where y is 'constant'.

A disassembly of that function reveals...

>>> import dis
>>> dis.dis(f)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_GLOBAL              0 (y)
              6 BINARY_ADD
              7 RETURN_VALUE

If you want to bind y to an object at the point of defining the lambda (i.e. creating a closure), it's common to see this idiom...

>>> y = 1
>>> f = lambda x, y=y: x + y
>>> f(1)
2
>>> y = 2
>>> f(1)
2

...whereby changes to y after defining the lambda have no effect.

A disassembly of that function reveals...

>>> import dis
>>> dis.dis(f)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 BINARY_ADD
              7 RETURN_VALUE
Sign up to request clarification or add additional context in comments.

3 Comments

While this is nifty, and what the OP was asking for, I feel sorry for the poor shmuck that has to maintain this. "Where the hell is y coming from in this lambda?!" It may be obvious in this example, but not in a larger project. Remember the python idiom "explicit over implicit"... I don' think this is explicit.
@JonathonReinhart I agree. I mainly posted this because the other answers implied that it wasn't possible, so I just wanted to demonstrate that it was possible. Whether or not it's a good idea is subjective. There's probably a better solution for what the OP wants to achieve, but the original question doesn't really contain enough info to make that determination.
I don't think "calling scope" is correct, as it implies dynamic binding. Python uses lexical binding.
1

f = functools.partial(lambda var, x: x + var.x - var.y, var) will give you a function (f) of one parameter (x) with var fixed at the value it was at the point of definition.

Comments

0

You cannot use the assignment statement in lambda expression, so you'll have to use a regular named function:

def f(x):
    global var
    var = x

Note the use of the "global" keyword. Without it, Python will assume you want to create a new "var" variable in the local scope of the function.

7 Comments

Upps. Sorry, assumed you wanted to assign to a variable, not to an object field. The "global" isn't needed in that case (as you're not introducing a new binding).
I don't consider using a global to be "assign[ing] a variable to the scope of" a function. That is a globally-scoped variable.
I am not sure how this helps in my case?
@JonasKlemming If the variable is in the global scope, changing it externally will change it everywhere, including inside the function. It's a bad idea, but it would work.
Ah ok, maybe using global is a solution after all.
|
-1

Make it another parameter:

f = lambda x,var: x + var.x - var.y
result = f(10, var)

Lambda or regular function, the only way you can change a variable in the scope of a function is via an argument.

7 Comments

Thanks, that was my first thought, but I want to avoid a second argument.
Well then how else can you do it? How do you possibly control what var is for each invocation of f?
In that case yes, re-define the lambda every place you want to use it. Seems silly and convoluted. (aka difficult to understand, maintain, etc.)
Why avoid a second argument? If you want two pieces of data, why obscure that?
Okay, but when it's not used, what is var then? This becomes so complicated. Perhaps you need to provide more information/code to help us understand what exactly you're trying to do. I would consider deleting this entire question and starting over.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.