71 lines
2.7 KiB
Plaintext
71 lines
2.7 KiB
Plaintext
From: gmcm at hypernet.com (Gordon McMillan)
|
|
Date: Thu, 20 May 1999 15:00:03 -0500
|
|
Subject: Circular references (was: Defining VCL-like framework for Py
|
|
In-Reply-To: <199905201737.TAA28177@axil.hvision.nl>
|
|
References: <7hvnah$ern$1@cronkite.cc.uga.edu>
|
|
Message-ID: <1284891865-6060292@hypernet.com>
|
|
Content-Length: 2413
|
|
X-UID: 1982
|
|
|
|
Ce'Nedra, er, Hans wrote:
|
|
|
|
> On 20 May 99, Ce'Nedra took her magical amulet and heard Graham
|
|
> Matthews say:
|
|
|
|
> >The problem is that as I understand the Python implementation you can very
|
|
> >easily make circular refs the without even knowing you are doing it via
|
|
> >globals. Or has this been changed?
|
|
>
|
|
> I don't know very much about this subject... I know it can be a
|
|
> problem with deleting objects... they sit in memory because there's
|
|
> still a reference to them, while you thought you deleted it. I can't
|
|
> really give an example though. I didn't hear about circular
|
|
> references via globals without even knowing it.
|
|
>
|
|
> I'm sure there are people who have more to say on this... *hint*
|
|
|
|
Oh all right.
|
|
|
|
I'm not sure where "globals" crept into this. If you have a global
|
|
reference, the referenced object ain't going away. You can have
|
|
*hidden* global references, but that's another problem, and it's not
|
|
particular to Python's ref counting scheme.
|
|
|
|
The problem is _usually_ a parent / child thing, where each has a
|
|
reference to the other. You cut them loose, but they don't go away
|
|
because each has another object (the other) referencing them.
|
|
|
|
You don't need to break _both_ references, just one of them. Simple
|
|
way out: give one of the objects a free() method which just says
|
|
"self.parent = None". Now you need to remember to call free() when
|
|
you're done with it.
|
|
|
|
Another way is to put one of them (the parent, normally) in some
|
|
kind of collection, (say, a dict keyed by a name, like id(parent)).
|
|
Tell the child the parent's name and the collection. When you cut the
|
|
parent loose from the dict, it goes away (the child does not directly
|
|
reference it). Then the child goes away (nobody is referencing it).
|
|
|
|
You can probably think of other ways of dealing with it. The
|
|
important part is recognizing them. Some of them can be subtle.
|
|
|
|
class LivesForever:
|
|
def __init__(self):
|
|
self.me = self
|
|
|
|
Despite these drawbacks, I generally prefer ref counting to garbage
|
|
collection. GC is generally nondeterminant - you know it _will_
|
|
happen, but you have no idea _when_. So if your objects have some
|
|
kind of outside resource open, you need to have a special free()
|
|
method anyway instead of relying on freeing it in the destructor.
|
|
|
|
I realize many people feel strongly the other way, and I'm not going
|
|
to fight about it. Neither solution is perfect. I'm just stating my
|
|
preference.
|
|
|
|
- Gordon
|
|
|
|
|
|
|
|
|