views:

211

answers:

2

I'm running a for loop inside a function which is creating instances of a class to test them. instead of making new classes it appears to be reusing the same two over and over.

Is there something I'm missing about how classes and variables are handled in python methods?

how can I generate a new object for each iteration of the loop

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,)

here is the output

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

when I use seperate variable names I get seperate ids for each instance as expected:

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)))

outputs:

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
+7  A: 

All that shows is that the memory of the objects is being reused, not that new objects aren't being instantiated. In each iteration collection is being overwritten, hence the previous object's reference count drops and the Python interpreter is free to deallocate its memory and reuse it (for the next object).

>>> 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

In this case, 2 memory locations are being reused. If you were to add it to a list (or save it elsewhere), it would be preserved:

>>> 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
codelogic
+2  A: 

from python documentation:

id() Return the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.

aaa
very nice, thanks for digging this up
Fire Crow