5 ms·
Here’s the crucial difference between Python destructors and C++ destructors: C++ destructors run as soon as the object goes out of scope, deterministically. Py
by tonyarkles 6y ago
Here’s the crucial difference between Python destructors and C++ destructors: C++ destructors run as soon as the object goes out of scope, deterministically. Python destructors run down the road, during the next GC cycle.
As an example of why this matters, I’ve got a class called TimeCapture in a project. If I want to instrument how long a block takes (full function, inside of an if, etc) I can add `TimeCapture tc(“my-metric-name”);` to the block and know that the destructor on that object will be called precisely at the end of that block (capturing the end time of the block)
I don’t know the rules for Swift or Ada or OP, but I’m guessing they’ll vary.
- kubav 6y agoTo implement scope guard you can use with statement and implement __enter__, __exit__ methods. It is not real RAII as object is not destroyed on exit but it is still quite useful. http://effbot.org/zone/python-with-statement.htm http://effbot.org/zone/python-with-statement.htm
- achn 6y agoHow do multiple destructors get sequenced? Last in, first out? Thanks
- masklinn 6y ago> Here’s the crucial difference between Python destructors and C++ destructors: C++ destructors run as soon as the object goes out of scope, deterministically. Python destructors run down the road, during the next GC cycle. Not true. They run when the object is deallocated. In CPython if the object is not involved in or referenced from a cycle, that’s as soon as it goes out of scope: the ref count goes to 0 and the object gets deallocated. This is trivial to check: create a structure with a noisy __del__ and create an instance from a function, call the function, del will run. The GC has no reason to run at this point, there’s no allocation requiring any sort of reclamation, but if you don’t trust that you can just `gc.disable()` and observe… the exact same behaviour.
- Nullabillity 6y ago> Not true. They run when the object is deallocated. In CPython if the object is not involved in or referenced from a cycle, that’s as soon as it goes out of scope: the ref count goes to 0 and the object gets deallocated. That's a CPython implementation detail, not a guarantee that you can rely on. For example, both PyPy[0] and Jython use tracing GCs where this is not true. [0]: https://doc.pypy.org/en/latest/cpython_differences.html https://doc.pypy.org/en/latest/cpython_differences.html
- masklinn 6y ago> That's a CPython implementation detail Which would be why I specifically wrote « in CPython ». And it still makes the original assertion completely incorrect. Python destructors do not run « down the road, during the next GC cycle ». They may, in certain cases or implementations.
- Nullabillity 6y agoOnce again, > implementation detail There is no guarantee that even CPython will keep the current behaviour. Ultimately, the promise you're given is that __del__ might be invoked by the system some point between "the object has no live references" and "never". The original assertion gives a much closer intuition than your description of the current behaviour.
- bluGill 6y agoNot all the world is CPython though. There are several other implemntions and the python docs make it quite clear that the cpython developers do not consider the a destructor running when an object goes out of scope anything more than an implementation detail, and they reserve the right to change it without warning should they discover a reason to. (They haven't changed it in 20 or 30 years, but that doesn't mean they won't tomorrow)
- masklinn 6y ago> Not all the world is CPython though The original commenter made a specific assertion. I demonstrated that their assertion is not true.