Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why is python reusing a class instance inside in function

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
like image 664
Fire Crow Avatar asked Dec 09 '09 21:12

Fire Crow


People also ask

Why is instance is used in Python?

Instance attributes are those attributes that are not shared by objects. Every object has its own copy of the instance attribute. For example, consider a class shapes that have many objects like circle, square, triangle, etc.

How do you reuse a function in Python?

And when it comes to reusing code in Python, it all starts and ends with the humble function. Take some lines of code, give them a name, and you've got a function (which can be reused). Take a collection of functions and package them as a file, and you've got a module (which can also be reused).

What does Python call when a new instance of a class is created?

The first method __init__() is a special method, which is called class constructor or initialization method that Python calls when you create a new instance of this class.

Is every object an instance of a class Python?

Every object has a type and the object types are created using classes. Instance is an object that belongs to a class. For instance, list is a class in Python. When we create a list, we have an instance of the list class.


2 Answers

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
like image 127
codelogic Avatar answered Nov 14 '22 23:11

codelogic


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.

like image 37
Anycorn Avatar answered Nov 14 '22 21:11

Anycorn