In both situation

__del__

doesn't work. I understand that 'del obj' don't delete all references, but why/how/which references created?

Example 1:

    class Exp:
        def __init__(self):
            self.b = 1
            self.a = lambda :self.b

        def __del__(self):
            print('a')

    obj = Exp()
    obj = None
    del obj

Example 2:

class Exp:
        def __init__(self):
            self.b = 1
            self.a = self.test

        def test(self):
            return 5

        def __del__(self):
            print('a')

    obj = Exp()
    obj = None
    del obj

There is no need to do an explicit del obj. Python does a __del__ automatically as soon as you do obj = None. If you comment out the lambda line you will get what you expect. I can't explain why the lambda line screws things up. I hate lambdas and never use them. Typically a lambda involves a parameter which is used in the calculation of the returned value like

x = lambda a: a * 2

In your case you are using self.b for a reason I do not understand but which seems irrelevant to your example.

commented: I'm sorry, i forgot to remove line with "obj None". I use self.b just for example. And i either can't understatnd why this happen. +0

I’m no Python expert, but my understanding is that del is called when and if the object is deleted by the garbage collecter. This may be some time after the last reference is released by obj = None, definitely not “as soon as you do obj = None”.
Maybe the test program needs to wait until there is a garbage cleaner pass before declaring the del as m.i.a.

Also, making a new reference to self in the destructor may increase the reference count by 1 and thus make the object ineligible for garbage collection / destruction. I believe this is called “resurrection” and can have unpredictable or bizarre consequences.

The problem is the self.b in the lambda. If you first delete self.a then it works as expected. Try

class Exp:
    def __init__(self):
        print('__init__')
        self.b = 1
        self.a = lambda: self.b

    def __del__(self):
        print('__del__')

obj = Exp()
obj.a = None
obj = None
commented: well, yes, but what happen in second example? +0

I presume the reasoning is the same as that for copy/deep copy. If you have a complicated structure, making a simple copy does not duplicate the nested objects. Because the lambda creates a nested object reference, deleting the object does not delete the lambda reference so the del does not get triggered and the object will not be released by garbage collection. In my last example I deleted the embedded reference, then deleted the object and the del was then called.

The destructor is a special member function in C++ that is responsible for releasing any resources that were allocated by an object during its lifetime. The destructor is automatically called when an object goes out of scope or when it is explicitly destroyed using the "delete" keyword.

If the destructor doesn't seem to be working, there are a few possible reasons why this might be happening:

The object might not be getting destroyed: If the object is not going out of scope or is not being explicitly destroyed using the "delete" keyword, the destructor will not be called. In this case, you should check that the object is being properly managed and destroyed.

The destructor might not be defined correctly: If the destructor is not defined correctly, it may not be releasing the resources that were allocated by the object. Make sure that the destructor is releasing all resources properly, including any dynamically allocated memory.

The object might have been deleted twice: If an object is deleted twice, it can cause memory corruption and other problems. In this case, the destructor may not be working correctly because the object is already destroyed.

There may be other issues with the code: If the destructor is not working correctly, there may be other issues with the code that are causing the problem. Make sure that the code is properly structured and that all objects are being managed correctly.

The destructor is automatically called when an object goes out of scope

Let's distinguish between an object and a reference to it. An object can be garbage collected when there are no more references to it. You can have more than one reference to an object.

>>> a = [1,2,3]
>>> b = a
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>> del a
>>> b
[1, 2, 3]
>>> a = None
>>> b
[1, 2, 3]
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.