[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