0

I have a problem with PyCharm. The Desctructor Method gets executed, without it even been called. If I try it in the Python IDLE the intepreter doesn´t iniatialize the __del__ method, but in PyCharm it does it

Input:

class Vehicle:
    def __init__(self, nme, ve):
        self.name = nme
        self.velocity = ve
    def __del__(self):
        print("Object", self.name, "got deleted")
    def beschleunigen(self, value):
        self.velocity += value
        self.output()
    def output(self):
        print(self.name, self.velocity, "km/h")

car1 = Vehicle("Ford",40)
car2 = Vehicle("BMW", 45)
    
car1.output()
car2.output()

Output:

Ford 40 km/h
BMW 45 km/h
Object Ford got deleted
Object BMW got deleted

As you can see the del function was not even called once and he still executes it

tdelaney
  • 73,364
  • 6
  • 83
  • 116
coder_sw99
  • 13
  • 2
  • 2
    Is it not just being [garbage collected](https://docs.python.org/3/glossary.html#term-garbage-collection)? – Random Davis Sep 24 '21 at 18:17
  • 2
    Once your program terminates, all objects are garbage collected and their `__del__` method called. – qouify Sep 24 '21 at 18:17
  • **`__del__` is not a destructor**. `__del__` is a *finalizer*. – juanpa.arrivillaga Sep 24 '21 at 18:20
  • `del` the keyword **doesn't delete objects**. Python != C++. Python is a memory-managed langauge, you have *no direct control* over the removal of objects from memory. In CPython, this is handled by *reference counting* as the main garbage collection strategy (with an auxiliary cyclic garbage collector). `del` removes a *name from a namespace*, so it is only indirectly related to `__del__` (because when a reference count goes to zero, an object becomes eligible for garbage collection. In the CPython implementation, it is "freed" immediately when this happens). – juanpa.arrivillaga Sep 24 '21 at 18:20
  • Note, in this particular case, because your objects are alive at the time of interpreter shutdown, `__del__` is not guaranteed to be called. Although it may still be. – juanpa.arrivillaga Sep 24 '21 at 18:27
  • Those dups don't explain the problem. Python calls `__del__` when an object's ref count goes to zero. After your script finishes execution, its a question of whether the thing running the script deleted the namespace holding car1 and car2. In normal script execution, everything in a script's namespace is deleteed and, assuming there weren't circular reference counts, everything gets its `__del__` called. IDLE didn't delete the namespace. It wants to keep those variables around for you. Same thing with `python3 -i test.py`. The namespace isn't deleted no `__del__` called. – tdelaney Sep 24 '21 at 18:29
  • @tdelaney those dupes explain exactly that, except more accurately. Strictly speaking, `__del__` is called "just before an instance is destroyed", it is a *finalizer*. In CPython, which uses a reference counting garbage collection strategy, this happens when a reference count reaches zero. This may not work like this in, say, Jython or Iron Python implementations. Also, your description about what happens when a script exits is not accurate. `__del__` is *not guaranteed to be called at all* for objects that are still alive when the program terminates and the interpreter shuts down. – juanpa.arrivillaga Sep 24 '21 at 18:33

1 Answers1

1

Python calls __del__ when an object's ref count goes to zero. The reference count goes up when an object is assigned to a variable, and down when that assignment is removed.

In your case, car1 and car2 are in the script's global namespace. After your script finishes execution, its a question of whether the thing running the script deleted the script's namespace. In normal script execution, everything in a script's namespace is deleted and, assuming there weren't circular reference counts, everything gets its __del__ called.

$ python3 test.py
Ford 40 km/h
BMW 45 km/h
Object Ford got deleted
Object BMW got deleted

That's how you ran your script in pycharm. But suppose the namespace isn't deleted? That's what happens with the -i option for example. The object's stick around until exit() is called.

$ python3 -i test.py
Ford 40 km/h
BMW 45 km/h
>>> print(car1)
<__main__.Vehicle object at 0x7fe3220ebcd0>
>>> exit()
Object Ford got deleted
Object BMW got deleted

that's what happened in your IDLE case.

As a side note, __del__ is not a destructor in the sense of C++. The supposed delete of an object as in del car1 really just removes the binding of car1 to its object and decrements the object reference count. Its deleting the variable car1, not the object referenced by car1.

tdelaney
  • 73,364
  • 6
  • 83
  • 116