13

在 c/c++ 中,当您在函数内创建局部变量时,堆栈中有变量。

http://effbot.org/zone/call-by-object.htm

CLU 对象独立于过程激活而存在。对象的空间是从动态存储区分配的 /.../ 理论上,所有的对象都会永远存在下去。实际上,当任何 CLU 程序不再可访问对象时,可以回收对象使用的空间。

这是否意味着 python 中的对象是从堆中创建的(就像 c/c++ 中的 malloc 一样)?并且对象在没有与之关联的名称时被释放?(如智能指针)?

例子:

def foo(a): 
  result = []
  result.append(a)
  return result

foo("hello")

myList = foo("bye")

那么第一个 result([]) 是在堆中创建的并且因为没有与之关联的名称而被释放?

4

3 回答 3

18

是的,所有 Python 对象都存在于堆上(至少在 CPython 上)。它们是引用计数的:当对对象的最后一个引用消失时,它们被解除分配。(CPython 还有一个垃圾收集器来打破循环。)

在 CPython 中,一旦函数返回,您的第一个列表就会消失,因为您没有将返回值绑定到名称并且引用计数降至零。在其他实现中,对象可能会存活更长时间,直到垃圾收集器启动。

一些对象(如打开的文件)具有附加的资源,这些资源在对象被释放时会自动释放,但由于上述原因,不建议依赖它。当你用完资源时,应该明确地关闭它们。

于 2012-07-27T13:25:48.880 回答
6

是的,CPython 中的所有值都分配在堆上并通过引用计数来知道何时释放它们。与 C 不同的是,在大多数情况下,无法知道一个值是否会比它的函数寿命更长,因此唯一安全的做法是对所有内容进行堆分配。

当然,您可以进行一些分析并确定某些值永远不会传递给函数,因此无法转义,但这在 Python 中的用途有限,而且额外的开销可能不值得。

于 2012-07-27T13:26:12.950 回答
6

作为其他答案的补充,这是一种使用特殊方法跟踪垃圾收集何时发生的方法__del__

class Test(object):
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print "deleting {0}".format(self.name)

print "discarded instance creation"
Test("hello")

print "saved instance creation"
myList = Test("bye")

print "program done"

输出:

丢弃的实例创建
删除你好
保存的实例创建
程序完成
删除再见

有关更深入的数据,请参阅gc 模块

于 2012-07-27T13:31:01.870 回答