下面是返回函数function
中定义的f
类型对象的程序,其堆栈框架(f1
)在程序退出之前仍处于活动状态。
下面是返回值为1024的int
类型对象的程序,但是在返回int
类型对象后堆栈框架不存在?
根据上面的两个图,当你返回int
类型对象时,为什么返回类型机制(帧不存活)的区别。
返回function
类型对象时,堆栈帧是否处于活动状态的想法是什么?
答案 0 :(得分:4)
“add_three是否引用n指向的同一个int对象?” - 是的,只有对int
的引用被传递并保持在帧中。在这种情况下,这适用于n
的任何值。
任何Python实现都允许保留不可变对象行int
的单个副本或多个副本 - 这对于该实现最方便,因为语义不会受到影响。
因此,在给定的实现中,每次提及文字3
都会引用相同的int
对象,但文字333
的提及不需要。 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)
两种情况的语义完全相同;在第一种情况下,编译器(一次在整个行上本质上调用)发现它很方便实例化并使用一个int
值333
,在第二种情况下,它更喜欢制作和使用两个这样的实例 - 考虑到int
的不变性,要么完全没问题(对于其他数字类型,字符串,元组,冻结集合也是如此 - 但对于可变类型则不然。)
请注意,当Python规范引用“相同语义”时,它明确包含内省,这可能能够查明语义等效状态之间的实现差异。
id
(通常返回对象的内存地址,在当前流行的Python实现中,但无论如何,只要对象存在,每个对象的唯一ID,根据语言规范)是内省的,如因此是is
运算符。因此,如果您希望使用它来理解某个实现可能执行的某些优化,那么您可以这样做。
关于你的其他问题:“我的理解是否正确?” - 不。
“为什么会出现这种差异” - def
构建一个可变的函数对象,因此即使具有相同函数定义的任何def
也必须返回一个新对象,就像例如[]
构建一个列表一样object,mutable,所以任何[]
都必须返回一个新对象。 3
构建一个int
对象,该对象是不可变的,因此允许任何3
(根据语言规则)返回相同或新对象。
在编辑中又添加了一个问题:“当返回函数类型对象时,堆栈帧的存在是什么想法?”
答案:每个物体都可以存活,只要它可以到达。只要返回内部(嵌套)函数,外部函数的框架就会保持活动状态,如果它们引用外部框架中的名称。
(任何Python实现都没有拥有来垃圾收集不再需要活动的对象 - 它可能会延迟垃圾收集,只要它喜欢,或者可以执行它立刻 - 实施细节! - )。