After reading my last post regarding __del__, you should know that __del__ + reference cycle = leak.
Let’s say that you do need to use __del__, so you decide to avoid reference cycles. You write your code in such a way as to use the minimum necessary cycles, and for the ones that remain you use the weakref module.
You might still have cycles where you don’t expect it – in references to methods.
Consider the following piece of code. Can you spot the reference cycle?
class A(object): def f(self): return a = A() a.g = a.f
This code has the following reference cycle: a -> a.g -> a.f -> a.
When you call a.f like so: “a.f()” two things happen:
1. A.f is bounded to a
2. The bounded A.f is called with the first parameter getting the bounded value.
You may consider that “a.f” is syntactic sugar for the partial function application, A.f gets a as a first argument but doesn’t get called yet.
When you use “a.g = a.f” what actually happens is a holding a reference to a bounded method, which holds a reference to a.
An idiom that uses these cycles is implementing state machines. Consider the following example code:
class MyMachine(object): def __init__(self): self.next_func = self.state_a def run(self, input): for x in input: self.next_func(x) def state_a(self, value): print 'a: ', value self.next_func = self.state_b def state_b(self, value): print 'b: ', value self.next_func = self.state_a
Of course, my code was a bit more complicated than that, but the basic idea remains. (My code usually created some kind of function table in __init__ used to lookup the next function, and lookups happened outside “state functions”). I’ve seen many state machine recipes include method references – and rightly so. It’s a clear and easy way to code a state machine. (For example, this state machine recipe).
Be careful though – once you add __del__ to these simple recipes you might end up with a memory leak.
Short note: I was going to publish this post a few days ago, but kylev beat me to it. This just goes to show that other people encountered this kind of cycle.