Tim Peters <t...@python.org> 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 <rep...@bugs.python.org> <https://bugs.python.org/issue40312> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com