4

I have this:

>>> a = lambda : lambda x : x * x 

This gives me a constant address every time:

>>> a
<function <lambda> at 0x7f22769e76e0>
>>> a
<function <lambda> at 0x7f22769e76e0>
>>> a
<function <lambda> at 0x7f22769e76e0>

However this does not. Why so? Also notice it gives only two addresses ? Why so? Is the inner lambda function being created on the fly and returned every time on calling a()? Was it not created when a was declared?

>>> a()
<function <lambda> at 0x7f22769e7320>
>>> a()
<function <lambda> at 0x7f22769e75f0>
>>> a()
<function <lambda> at 0x7f22769e7320>
>>> a()
<function <lambda> at 0x7f22769e75f0>
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • 2
    I'm guessing that the two addresses part is due to the special variable `_` that is created to hold the result of the previous calculation in an interactive session. Since there's a reference to it, the returned value (that you see the `repr` of) only gets garbage collected after a second statement has been run (replacing the reference in `_`). In a non-interactive script you might get the same address for all of them (though still probably not the same object, just reused memory). – Blckknght Aug 14 '13 at 02:05
  • @Blckknght You're right - I tested it and in a script the address is the same, though I'm still very confused about why. Can you provide a link with more information or give a more detailed answer? – Mike Vella Aug 14 '13 at 02:07
  • 2
    Interesting, `print a()` doesn't have the same behaviour – Aert Aug 14 '13 at 02:12
  • what is the behaviour @Aert? – Mike Vella Aug 14 '13 at 02:14
  • Same address every time! – Aert Aug 14 '13 at 02:15
  • Assuming your question is about why there are only two addresses, this is a duplicate of [Object methods of same class have same id?](http://stackoverflow.com/questions/16727490/object-methods-of-same-class-have-same-id) – Asad Saeeduddin Aug 14 '13 at 02:17
  • @Asad Took me some time to get my head around, but that's really nice insight. – Mike Vella Aug 14 '13 at 02:19
  • @Aert I think I understand why you're getting the same address each time as well. When you use `print a()` (the old syntax), **the result is not stored in `_`**, since it returns nothing. That means there are no references to the created lambda, and it is gcd immediately. Blckknght is right on the money here. To test this out, store the results of invoking a in a variable and watch the addresses change. – Asad Saeeduddin Aug 14 '13 at 02:22
  • @Asad What do you guys mean by '_' - it's impossible to google. – Mike Vella Aug 14 '13 at 02:43
  • 1
    @MikeVella Try typing any expression that produces a value into the interpreter, but don't assign it to anything. Then check what the value of `_` is. – Asad Saeeduddin Aug 14 '13 at 02:44
  • 1
    eg. `>>> 5 | 5 | >>> _ | 5` (`|` represents line breaks) – Asad Saeeduddin Aug 14 '13 at 02:45
  • @Asad that's something I never knew! however print('something') and print 'something' both don't affect _ in Python2.7 at least. – Mike Vella Aug 14 '13 at 02:47
  • 1
    @MikeVella That's because neither of those produce a value! For example, consider the function `def a(var): pass`. Invoke it, and it doesn't produce a value. That means `_` stays unaffected – Asad Saeeduddin Aug 14 '13 at 02:48
  • @Asad so what were you referring to by 'the old syntax'? From your answer I got the impression that the 'new syntax' (Python 3?) did something different? perhaps I'm just confused. – Mike Vella Aug 14 '13 at 02:50
  • 1
    @MikeVella `print` was turned into a function in Python 3, whereas it was a statement in Python 2.x – Asad Saeeduddin Aug 14 '13 at 02:51
  • 1
    @MikeVella The syntax is pretty much irrelevant. If `print` is confusing you, imagine I had defined the function `def f(somevalue): pass` and was repeatedly doing `f(a())`. That doesn't store a reference to the result of `a()` anywhere either, so you'll still see the same results. – Asad Saeeduddin Aug 14 '13 at 02:53
  • @Asad OK - so its the language not the syntax which has changed per se, since print('print something') is still valid Python2 syntax, but it (confusingly) has a different implementation in Python3. I understand now, thanks for the great comments! – Mike Vella Aug 14 '13 at 02:54

2 Answers2

2

a is the function itself, as a variable. Its address won't change unless it is moved in some manner in memory.

a() actually calls the function. A function will not do anything until it is called via (). So yes, here your inner lambda function is being created on the fly. That will be the addresses you see there. As Blckknght commented, garbage collection probably leads to the reuse of memory.

Michal
  • 2,532
  • 1
  • 19
  • 27
1

Yes, your understanding is correct: the "inner" lambda is only created when the "outer" lambda is evaluated, which doesn't happen until it (the outer) is invoked.

brianmearns
  • 9,581
  • 10
  • 52
  • 79
  • It has nothing to do with Python being an interpreted language. The inner lambda should also only be instantiated when the outer is evaluated in a compiled language. – Mike Vella Aug 14 '13 at 02:10
  • Good point, I'll update my answer to make sure there's no misinformation. In the case of a lambda, a compiled language would probably act the same, but the OP seems to be working on the assumption that python will somehow evaluate the definition of the function `a` prior to actually executing it. A compiled language would have that option, but most likely would not act on it for a lambda. It may do so for other things, like literal arithmetic expressions or compile-time address resolution, whereas a strictly interpreted language doesn't even have the option. – brianmearns Aug 14 '13 at 02:27