Tim Peters <[email protected]> added the comment:
Well, the refcounts on _everything_ cyclic gc sees are greater than 0. Because
if an object's refcount ever falls to 0 in CPython, reference counting deals
with it immediately, and so it doesn't survive to participate in cyclic gc.
IOW, absolutely everything cyclic gc deals with is "strongly referenced" in the
sense you're using: absolutely everything cyclic gc deals with has a nonzero
refcount. Indeed, in a debug build, gc asserts early on that everything it
sees has a refcount > 0.
It can be trash anyway. Finding those "just internal references" is the
_point_ of cyclic gc. In your last example, the instant after you did `del o`,
the instance of Foo, and the instance of Bar, _both_ became trash, period,
despite that they both retained positive refcounts.
So you may as well object that the refcount of `self` is also greater than 0
inside __del__. Indeed, add
print(sys.getrefcount(self))
inside your __del__, and you'll see it prints 4. So it's _twice_ as "strongly
referenced" as self.value ;-) It's being destroyed anyway.
Refcounts are simply irrelevant at this point, and so also is the concept of
"strong reference" on its own. All that matters is whether a strong reference
exists from _outside_ the generation being collected. `self` and `self.value`
are in exactly the same boat in this regard: there are no strong references to
either from outside, but there are strong references to both from inside.
They're both trash.
There is _a_ principled way to proceed that would get you what you want in this
example, but CPython never pursued it because it would add major complexity for
almost no apparent practical gain: build a graph of all the cyclic trash,
compute the strongly connected components, build the induced DAG composed of
the SCCs, then run end-of-life actions in order of a topological sort of that
DAG. Then __del__ would run first (self is in a self-cycle SCC with no
predecessors in the DAG), and the weakref callback second (the Bar instance
would be in its own SCC, with the `self` SCC as its predecessor in the DAG).
But I'm not sure any real gc system does that.
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue40312>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com