0

Within a loop, I'm building a collection of anonymous functions. The problem is that I want to define each function in terms of the current value of the variable I'm looping over, but when this variable changes, the function retrospectively changes because values are passed by reference.

Here's a simplified example:

c = 8
f = lambda x: x+c

f(1)  # returns 9

c = 100 
f(1)  # returns 101

What's an idiomatic way to define a function in an immutable way so that further changes to other variables don't generally redefine the function's behavior? (I expect this question has come up before, but I wasn't able to locate a duplicate question on Stack Overflow.)

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 1
    values **are never passed by reference in Python**. Never. You are seeing the effects of using a global variable. However, the situation you describe would also occur with free variables, say, in some function, `funcs = []; for i in range(2): funcs.append(lambda : i)`, due to lexical scoping The solution is the same as those provided in the duplicate and by @Ry- in the comments below – juanpa.arrivillaga Jan 06 '20 at 21:10
  • 4
    The hacky way that’s also a well-recognized idiom in Python is to do `lambda x, c=c: x+c`. A more reliable way is to have a separate function that accepts the captured values as parameters and returns a lambda, e.g. `def make_f(c): return lambda x: x+c`, which *can* be written inline as `(lambda c: lambda x: x + c)(c)`. – Ry- Jan 06 '20 at 21:10
  • Also, to put what @juanpa.arrivillaga said another way, there’s indeed no passing by reference going on here (`c` isn’t passed at all, passing is something you do with arguments, and Python doesn’t have pass-by-reference). Instead, `c` is literally the same variable inside the lambda as outside. (And maybe you get that, and capturing/closing over is a kind of referencing, but may as well point this out.) – Ry- Jan 06 '20 at 21:13
  • Also, note, this isn't a special behavior of lambda functions, all functions work this way in Python. – juanpa.arrivillaga Jan 06 '20 at 21:16
  • @Ry- absolutely. This is fundamentally an issue of variable scope, not evaluation strategy, since as you state, there are no function arguments getting passed. Another one of my pet peeves are people conflating evaluation strategy and assignment semantics. – juanpa.arrivillaga Jan 06 '20 at 21:26

0 Answers0