2

Below is the program that returns function type object defined in function f whose stack frame(f1) is still alive until the program exits.

enter image description here


Below is the program that returns int type object whose value is 1024, but the stack frame does not exist after we return int type object?

enter image description here


As per the above two diagrams, Why this difference in return type mechanisms, where frame is not alive, when you return int type object.

What is the idea for stack frame being alive when function type object is returned?

4
  • 1
    The distinction made in the diagrams is that functions are mutable objects, while integers are not. But both are returned as references... Commented Feb 2, 2015 at 4:11
  • You have to be really careful when arguing with small integers < 256, as they are globally interned. Also, in the second example your just passing n through, what do you expect to happen? Commented Feb 3, 2015 at 9:00
  • @filmor What I would like to confirm is, In second example, Does add_three refer to same int object that n is pointing to? This is where I am asking whether the return mechanism is by copy? For simplicity, assume the value is > 256. Commented Feb 3, 2015 at 11:59
  • Yes, it does. When calling the function you are passing a reference to the object, that you return unchanged in the end. If you'd do something like n *= 1 the returned object would be different, as that changed the reference n. This is where the small integer optimisation is important, since id(n * 1) == id(n) iff n is a small integer. Commented Feb 3, 2015 at 13:44

1 Answer 1

4

Python never make copies unless explicitly asked to (for example, slicing a list does ask Python to copy that part of the list, shallowly).

"Does add_three refer to same int object that n is pointing to?" -- yes, only references to that int are being passed around and held in frames. In this case this applies whatever the value of n.

Any Python implementation is allowed to keep a single copy, or multiple copies, of immutable objects line ints -- whatever's most convenient to that implementation, given the semantics are not affected anyway.

So in a given implementation it could happen that every mention of literal 3 refers to the same int object but mentions of literal 333 need not. E.g:

2>>> a=333; b=333; print(id(a), id(b))
(4298804944, 4298804944)
2>>> a=333
2>>> b=333
2>>> print(id(a), id(b))
(4298753600, 4298753336)

The semantics of the two cases are absolutely identical; in the first case the compiler (intrinsically called on the whole line at once) finds it handy to instantiate and use a single int worth 333, in the second case it prefers to make and use two such instances -- either is completely fine, given int's immutability (same goes for other number types, strings, tuples, frozen sets -- but not for mutable types).

Note that when the Python specification refers to "same semantics", it explicitly includes introspection, which may be able to pinpoint implementation differences between semantically equivalent states.

id (normally returning the memory address of an object, in current popular implementations of Python, but in any case an id that's unique per object as long as the object lives, per language specs) is introspection, as consequently is the is operator. So you can if you wish use it to understand some optimizations a given implementation may perform, or not.

So on to your other Qs: "Is my understanding correct?" -- no. "Why this difference" -- def builds a function object, which is mutable, so any def even with identical function definitions must return a new object, just like e.g [] builds a list object, mutable, so any [] must return a new object. 3 build an int object, which is immutable, so any 3 is allowed (per language rules) to return either the same or a new object.

One more question was added in an edit: "What is the idea for stack frame being alive when function type object is returned?"

Answer: every object stays alive as long as it's reachable. An outer function's frame, in particular, stays alive as long as inner (nested) functions is returned, if they refer to names in the outer frame.

(Any Python implementation doesn't have to garbage-collect objects that don't any more need to be alive -- it may delay that garbage collection as long as it pleases, or can perform it at once -- implementation details!-).

Sign up to request clarification or add additional context in comments.

6 Comments

@overexchange, ok, but there's nothing in your edit that in any way invalidates my A or needs any addition -- it's exactly what I explained in my A. You apparently don't like my A, but neither do you give any indication of what you think it leaves unanswered! Ah well, I'll edit to remove the last, now-unneeded para.
@overexchange, added answer to your new and somewhat unrelated question.
why function type objects are chosen to be mutable and int type objects are chosen to be immutable? Am still not clear, How mutable/immutable factor has something to do with existence of frame f1?
@overexchange, all numbers and strings are immutable by design for the same design decisions Java took years later -- it's handier and faster and allows effective hash tables (dictionaries and sets, in Python). The outer frame of g is not reachable, so any Python implementation could choose to garbage collect it if if wanted -- if yours doesn't, it's an implementation-convenience choice. The only effect of functions being mutable is no implementation's allowed to return the same obj for result1 and result2, as changes to one can't affect the other (def creates a new function obj).
Now I understand the meaning of function objects being mutable. But When you say, could choose to garbage collect, Does that mean, if n was not used in function g garbage collector could have deleted outer frame of g which is f1 as mentioned in my first diagram? Am still not clear, why garbage collector did not delete frame f1
|

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.