[SciPy-Dev] Circular reference in interp1d causing memory errors
Matthew Brett
matthew.brett at gmail.com
Sat May 18 16:13:08 EDT 2013
Hi,
On Sat, May 18, 2013 at 5:17 AM, Robert Kern <robert.kern at gmail.com> wrote:
> On Sat, May 18, 2013 at 12:14 PM, <josef.pktd at gmail.com> wrote:
>
>> interp._call is an instance method assigned in the __init__
>> This is a pattern we use quite a few times (stats.distribution does it
>> a lot, statsmodels in some models).
>>
>> I know we have problems with pickling in these cases, but didn't know
>> about the garbage collection.
>>
>> I didn't find much explicit information after googling for an hour.
>> http://stackoverflow.com/questions/9329232/internal-reference-prevents-garbage-collection
>> looks similar but doesn't use create instance methods.
>
> Yes, this is the same issue, just storing the bound methods in a dict
> rather than directly as an attribute on the instance.
>
>> The solution
>> with calling through the class might be interesting in some cases.
>> I found a few more threads on various mailing lists but never a clear
>> answer or link.
>>
>> Does anyone know a more explicit explanation?
>> Or, is it really just the cyclical reference, even though it's a
>> method (which always hold self)
>
> The bound method is not created with the .im_self reference until it
> is requested. Until then, the *unbound* method lives on the class
> without a reference to any particular instance.
>
> [~]
> |1> from scipy.interpolate import interp1d
>
> [~]
> |2> f = interp1d(np.linspace(0,1), np.linspace(0,1))
>
> [~]
> |3> f._call_linear is f._call_linear
> False
>
>
> Requesting the method creates a new bound method that refers to the instance.
>
> [~]
> |4> f._call_linear.im_self
> <scipy.interpolate.interpolate.interp1d at 0x10b4f8710>
>
> [~]
> |5> f
> <scipy.interpolate.interpolate.interp1d at 0x10b4f8710>
Thanks - I didn't realize this - that each time I do this:
obj.method
- I get a new method object. Because I had to explain this to
myself, and more or less repeating Robert's exposition:
In [1]: class C(object):
...: def method(self):
...: pass
...:
In [2]: c = C()
In [3]: m1 = c.method
In [4]: m2 = c.method
In [5]: m1
Out[5]: <bound method C.method of <__main__.C object at 0x1958550>>
In [6]: m2
Out[6]: <bound method C.method of <__main__.C object at 0x1958550>>
In [7]: m1 is m2
Out[7]: False
In [8]: id(m1)
Out[8]: 26609456
In [9]: id(m2)
Out[9]: 26609696
http://docs.python.org/2/reference/datamodel.html
Thanks for the discussion,
Matthew
More information about the SciPy-Dev
mailing list