Python Delegate Pattern - How to avoid circular reference?

2024/10/6 10:31:37

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:

  1. 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?
  2. 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.

Answer

Python already does garbage collection. You only need to do something special if you write your own container types in C, as extensions.

Demo: Run this program and watch the memory usage not climb.

class C(object):passdef circular():for x in range(10**4):for y in range(10**4):a = C()b = C()a.x = bb.x = acircular()

Footnote: The following function doesn't do anything, delete it.

def setDelegate(self, delegate):self.delegate = delegate

Instead of calling x.setDelegate(y), you can use x.delegate = y. You can overload member access in Python, so there's no benefit to writing a method.

https://en.xdnf.cn/q/70382.html

Related Q&A

Render Jinja after jQuery AJAX request to Flask

I have a web application that gets dynamic data from Flask when a select element from HTML is changed. of course that is done via jquery ajax. No probs here I got that.The problem is, the dynamic data …

shape-preserving piecewise cubic interpolation for 3D curve in python

I have a curve in 3D space. I want to use a shape-preserving piecewise cubic interpolation on it similar to pchip in matlab. I researched functions provided in scipy.interpolate, e.g. interp2d, but …

ForeignKey vs OneToOne field django [duplicate]

This question already has answers here:OneToOneField() vs ForeignKey() in Django(12 answers)Closed 9 years ago.I need to extend django user with some additional fields . I found 2 different ways there…

How to sort glob.glob numerically?

I have a bunch of files sorted numerically on a folder, when I try to sort glob.glob I never get the files in the right order.file examples and expected output sorting folder ------ C:\Users\user\Deskt…

How to determine a numpy-array reshape strategy

For a python project I often find myself reshaping and re-arranging n-dimensional numpy arrays. However, I have a hard time to determine how to approach the problem, visualize the outcome of the result…

matplotlib plotting multiple lines in 3D

I am trying to plot multiple lines in a 3D plot using matplotlib. I have 6 datasets with x and y values. What Ive tried so far was, to give each point in the data sets a z-value. So all points in data …

How to get a telegram private channel id with telethon

Hi cant figure out how to solve this problem, so any help will be really appreciated. Im subscribed to a private channel. This channel has no username and I dont have the invite link (the admin just ad…

boolean mask in pandas panel

i am having some trouble masking a panel in the same way that I would a DataFrame. What I want to do feels simple, but I have not found a way looking at the docs and online forums. I have a simple ex…

How can I move the text label of a radiobutton below the button in Python Tkinter?

Im wondering if theres a way to move the label text of a radiobutton to a different area, e.g. below the actual button.Below is an example of a few radiobuttons being placed using grid that Im using:fr…

play sound file in PyQt

Ive developed a software in PyQt which plays sound.Im using Phonon Library to play the sound but it has some lag.So how can I play a sound file in PyQt without using Phonon Library.This is how I am cur…