2

我有一个名为的类Door和一个名为Window. 它是一个名为 的类的子类Furniture。我的程序读取 excel 文件,循环 2 次,第一次读取/写入有关门的所有内容,第二次读取/写入有关 windows 的所有内容。简化,我有以下代码:

for gathering_inf in ('door', 'window'):
    for row in file:
        if gathering_inf == 'door' and currently reading door line:
            furniture = Door(width, height, description)
        if gatherig_inf == 'window' and currently reading window line:
            furniture = Window(width, height, description)

        # Now do something with the furniture object ..

发生的奇怪想法是,如果我例如(如上所示)打印对象furniture,我得到它们的位置,并且一些对象在内存中的位置是相同的,即使它们是两个不同的实例宽度不同的属性。例如:

<__main__.Door object at 0x03BFE810>
<__main__.Door object at 0x03BFE890>
<__main__.Door object at 0x03BFE810>
<__main__.Door object at 0x03BFE890>
<__main__.Door object at 0x03BFE8B0>
<__main__.Door object at 0x03BFE8D0>
<__main__.Door object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE8D0>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>
<__main__.Window object at 0x03BFE8B0>
<__main__.Window object at 0x03BFE890>

有人可以向我解释为什么 python 会这样吗?

4

2 回答 2

4

那是因为引用计数垃圾收集器。一旦一个新对象被分配给furnitureGC 将删除该对象,因此它的内存位置可以被一个新对象重新使用。


这是一个显示此行为的小演示。请注意,由于 Python REPL 的工作方式(它保留对最后一个结果的引用_),地址将交替出现。

>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
>>> foo = object(); foo
<object object at 0x7fd74cd390b0>
>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
>>> foo = object(); foo
<object object at 0x7fd74cd390b0>
>>> foo = object(); foo
<object object at 0x7fd74cd390a0>
于 2012-12-23T13:49:57.310 回答
1

ThiefMaster几乎做到了:这就是 Python 虚拟机的工作方式。

您正在观察的是参考计数垃圾收集器的CPython实现的细节。在您的情况下, CPython是垃圾收集对象,然后创建一个新对象,然后重用(现在垃圾收集的)对象的位置,将对象存储在那里。DoorWindowDoorWindow

事实上, CPython重用以前被垃圾回收的对象的地址是很常见的。例如,在我的电脑上运行 ThiefMaster 的代码,我得到了稍微不同的(旋转)结果:

CPython 内存使用情况

在这一点上,重要的是要注意这种行为是CPython特定的。例如,Enthought 的 Python Distribution似乎没有产生类似的结果,但是我不知道这种不一致是否是实现差异的问题:

在此处输入图像描述

于 2012-12-23T14:01:42.800 回答