I would to ask if using the Delegate Pattern in Python would lead to circular references and if so, what would be the best way to implement it to ensure the object and its delegate will be garbage collected?
In Objective C, the above problem is avoided by using a weak reference to the delegate. In C++, we don't call delete on the delegate. I've found a link to Python's weak reference module here: http://docs.python.org/library/weakref.html. It seems like a plausible approach might be to create a weak reference to refer to the instance variable using this module but I'm not sure.
As I've googled this question and was not able to find answers to it, I'm wondering whether this is even a problem in Python or if there is a common solution (without the need for the weakref module) that I'm unaware of? Also, I did search stackoverflow before asking but the questions I found either deal with circular imports or delegate pattern in general and not specific to Python and the problem of circular references.
Thanks in advance for any replies.
Listed below is some code for a toy example to help illustrate my question. I've implemented code in this way and it works but I'm not sure whether memory is garbage collected at the end.
class A(object):def __init__(self):self.delegate = None# Some other instance variables that keep track of state for performing some tasks.def doSomething(self):if self.delegate is not None:self.delegate.doSomething()else:print('Cannot perform task because delegate is not set.')# Other methods not shown.class B(object):def __init__(self):self.a = A() # Need to keep object 'a' from garbage collected so as to preserve its state information.self.a.delegate = self # Is this a circular reference? How to 'fix' it so that A and B will eventually be garbage collected?def doSomething(self):print('B doing something')# Other methods not shown.
EDIT:
After reading some of the replies, I decided to clarify my question. I understand that Python has garbage collection. What I wasn't sure was whether it will perform garbage collection on circular referenced objects. My worries stems from the following passage from Python's doc:
CPython implementation detail: CPython currently uses areference-counting scheme with (optional) delayed detection ofcyclically linked garbage, which collects most objects as soon as theybecome unreachable, but is not guaranteed to collect garbagecontaining circular references. See the documentation of the gc modulefor information on controlling the collection of cyclic garbage. Otherimplementations act differently and CPython may change. Do not dependon immediate finalization of objects when they become unreachable (ex:always close files).
The passage in its original form can be found here: http://docs.python.org/reference/datamodel.html The bold setting is mine.
The following post provides a clearer explanation on the problem of circular referenced objects and why it would prevent garbage collection on those objects (at least in a typical setting): http://www.electricmonk.nl/log/2008/07/07/python-destructor-and-garbage-collection-notes/.
Further, I just came across Alex Martellli's reply to the following question on whether Python users should worry about circular reference: Should I worry about circular references in Python? From his answer, I gather that even though circular referenced objects will eventually be garbage collected BUT there would be overheads. Whether it is significant depends on the program.
Further, he mentioned to use Python's weakref module but did not explicitly say how.
Hence, I would like to add the following questions to clarify some unresolved issues:
- The docs say garbaged collection is not guaranteed for circular referenced objects. But from the replies it appears that is not the case. So have I misunderstood the passage or are there further details that I've missed?
- I suppose using a weak reference, as stated in Alex's reply and my question, would avoid the overhead the problem entirely?
Again thanks for the replies.