I have a very complex class:
class C: pass
And I have this test code:
for j in range(10): c = C() print c
What gives:
<__main__.C instance at 0x7f7336a6cb00> <__main__.C instance at 0x7f7336a6cab8> <__main__.C instance at 0x7f7336a6cb00> <__main__.C instance at 0x7f7336a6cab8> <__main__.C instance at 0x7f7336a6cb00> <__main__.C instance at 0x7f7336a6cab8> <__main__.C instance at 0x7f7336a6cb00> <__main__.C instance at 0x7f7336a6cab8> <__main__.C instance at 0x7f7336a6cb00> <__main__.C instance at 0x7f7336a6cab8>
It is easy to see that Python includes two different values. In some cases, this can be catastrophic (for example, if we store objects in some other complex object).
Now, if I store the objects in a list:
lst = [] for j in range(10): c = C() lst.append(c) print c
I get this:
<__main__.C instance at 0x7fd8f8f7eb00> <__main__.C instance at 0x7fd8f8f7eab8> <__main__.C instance at 0x7fd8f8f7eb48> <__main__.C instance at 0x7fd8f8f7eb90> <__main__.C instance at 0x7fd8f8f7ebd8> <__main__.C instance at 0x7fd8f8f7ec20> <__main__.C instance at 0x7fd8f8f7ec68> <__main__.C instance at 0x7fd8f8f7ecb0> <__main__.C instance at 0x7fd8f8f7ecf8> <__main__.C instance at 0x7fd8f8f7ed40>
What solves this case.
So now I have to ask a question ... Can someone explain with complex words (I mean, deeply) how Python behaves with references to objects? I suppose this is an optimization issue (to free up memory or prevent leaks, ...)
Many thanks.
EDIT: Well, let me be more specific. I understand perfectly that python sometimes collects garbage ... But in my case:
I had a list returned by a specific Cython: class 'Network' class that manages a Node list (both Network and Node are defined in the Cython extension ). Each Node has an object [then it is placed in an object (void *)] 'userdata'. The Nodes list is populated from within cython, and the UserData is populated inside the Python script. So in python, I had the following:
... def some_python_class_method(self): nodes = self.netBinding.GetNetwork().get_nodes() ... for item in it: a_site = PyLabSiteEvent()
Reusing this Node list in the same python class using the same cython recipient:
def some_other_python_class_method(self, node): s_data = node.GetUserData() ...
So it looks like with the repository made in the Node UserDatas user list, my python script was completely blind and freed / reused memory. It worked by referencing a second time (but apparently the first to the python side) using an optional list (here: 'l_site'). That's why I should have learned a little more about Python itself, but it seems that the way I implemented the connection between Python and Cython is responsible for the problems I had to deal with.