Sorry to reply in this old thread. We just noticed this on #pypy:
On 22 October 2016 at 05:32, Nick Coghlan email@example.com wrote:
The weakref-before-__del__ ordering change in https://www.python.org/dev/peps/pep-0442/#disposal-of-cyclic-isolates only applies to cyclic garbage collection,so for normal refcount driven object cleanup in CPython, the __del__ still happens first:
>>> class C: ... def __del__(self): ... print("__del__ called") ... >>> c = C() >>> import weakref >>> def cb(): ... print("weakref callback called") ... >>> weakref.finalize(c, cb) <finalize object at 0x7f4300b710a0; for 'C' at 0x7f42f8ae3470> >>> del c __del__ called weakref callback called
Nick, it seems you're suggesting that before PEP 442 (in CPython 3.4) the __del__ happened before the weakref-clearing operation as well. That's not the case: before CPython 3.4, weakrefs are always cleared first. The situation became more muddy in 3.4, where weakrefs are usually cleared after the __del__ is called---in the absence of reference cycles (so it's a backward-incompatible change). If there are reference cycles, then the weakref is cleared before the __del__ is called.
This can be shown in your example by replacing "weakref.finalize(c, cb)" with an old-style "wr = weakref.ref(c, cb)". Then CPython <= 3.3 and >= 3.4 print the two lines in opposite order.