为什么Python在函数内部复用类实例

6 投票
2 回答
3158 浏览
提问于 2025-04-15 16:51

我在一个函数里运行了一个循环,这个循环用来创建一个类的实例进行测试。但是我发现,它似乎一直在重复使用同两个实例,而不是每次都创建新的。

我是不是对Python中的类和变量处理有什么误解呢?

我该如何在循环的每次迭代中生成一个新的对象呢?

class CollectionSetImages(unittest.TestCase):
    def test_keywordset(self):
        """Testing keyword queries by images equality """

        for keyword in ['a','b','c','d','e','f','g']:
            images_by_keyword = Image.keyword_query([keyword])
            collection = Collection([keyword]) 
            class_images = collection.images
            print('colleciton: %s id: %s' % (collection,id(collection)))
            self.assertEqual(images_by_keyword, class_images,)

这是输出结果

colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656cc> id: 3083228876
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656ec> id: 3083228908
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656cc> id: 3083228876
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656ec> id: 3083228908
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656cc> id: 3083228876
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656ec> id: 3083228908
colleciton: <tests.fakeimages._FakeCollection object at 0xb7c656cc> id: 3083228876

当我使用不同的变量名时,每个实例的ID都是不同的,正如我预期的那样:

collectionA = Collection(['a'])  
print('collection: %s id: %s' % (collectionA,id(collectionA)))

collectionB = Collection(['f'])
print('collection: %s id: %s' % (collectionB,id(collectionB)))

collectionC = Collection(['f'])
print('collection: %s id: %s' % (collectionC,id(collectionC)))

输出结果:

collection: <tests.fakeimages._FakeCollection object at 0xb7cbc8ac> id: 3083585708
collection: <tests.fakeimages._FakeCollection object at 0xb7cbccec> id: 3083586796
collection: <tests.fakeimages._FakeCollection object at 0xb7cbcd2c> id: 3083586860

2 个回答

4

来自Python文档:

id() 是一个函数,用来返回一个对象的“身份”。这个身份是一个整数(或者长整数),在这个对象的整个生命周期内都是唯一的和不变的。也就是说,只要这个对象还在,它的身份就不会改变。不过,如果两个对象的生命周期没有重叠,它们可能会有相同的 id() 值。

11

这段话的意思是,显示的只是对象的内存被重复使用,并不能说明没有创建新的对象。在每次循环中,collection 的内容被覆盖了,因此之前对象的引用计数减少,Python解释器就可以释放它的内存并重新使用(给下一个对象)。

>>> for a in range(1,5):
...     b = object()
...     print b, id(b)
... 
<object object at 0xb7db9470> 3084620912
<object object at 0xb7db9468> 3084620904
<object object at 0xb7db9470> 3084620912
<object object at 0xb7db9468> 3084620904
<object object at 0xb7db9470> 3084620912

在这种情况下,有两个内存位置被重复使用。如果你把它添加到一个列表中(或者保存到其他地方),那么它就会被保留下来:

>>> a = []
>>> for b in range(1,5):
...     c = object()
...     a.append(c)
...     print c, id(c)
... 
<object object at 0xb7db9470> 3084620912
<object object at 0xb7db9468> 3084620904
<object object at 0xb7db9478> 3084620920
<object object at 0xb7db9480> 3084620928

撰写回答