3

Here is my class definition :

class Playingsound:
    def ___init___(self):
        # blah

    def fadeout_and_stop(self):
        # do somthing (fadeout during 100 ms)
        del self

Here is my problem (similar to that one : Python object deleting itself) :

>>> a = Playingsound()
>>> time.sleep (1.0)
>>> a.fadeout_and_stop()
>>> time.sleep (1.0)    # after 1 second, the playback should be finished !
>>> a
<__main__.Playingsound instance at 0x01F23170>

Instead of this, I would like a to be totally destroyed after the call of fadeout_and_stop, and its reference to be None :

>>> a
<None>

How to do this with Python ?

Community
  • 1
  • 1
Basj
  • 41,386
  • 99
  • 383
  • 673
  • 1
    What is the actual problem you are trying to solve here? Why can't you write `del a` instead of `a.finish()`? – NPE Dec 24 '13 at 09:21
  • 3
    You cannot, not without looping through **all** references in the garbage collector and testing each and every one if it is a reference to *this* object, then setting that reference to `None`. You don't want to go there. – Martijn Pieters Dec 24 '13 at 09:22
  • As a small point - if you aren't doing anything in a method, you don't need to define it just to add `pass` in the body. Also, the method is `__init__` (note two `_` you have three `_`). Like @NPE I am also curious as to why you need this. If you are trying to write a deconstructor - that is not required in Python as the GC does a good job of keeping names only when needed. – Burhan Khalid Dec 24 '13 at 09:24
  • `A` is a class for a currently playing sound buffer. `finish` is my "stop playback" method. When somebody does `finish` I would to do things (apply a fadeout, still play for 100 ms) and then `delete` the `A` sound object. – Basj Dec 24 '13 at 09:24
  • In your player class (which I assume has a list of "tracks" to play), simply delete that object from the list of tracks once its done playing, something like `self.track_list.pop()`. The rest will be handled by Python automatically. – Burhan Khalid Dec 24 '13 at 09:28

3 Answers3

4

You cannot, not without looping through all references in the garbage collector and testing each and every one if it is a reference to this object, then setting that reference to None. You don't want to go there. Remember: you can have more than one reference to your object:

a = A()
b = a
a.finish()  # what should be set to `None` now? a, b or both?

Instead of a.finish(), do del a, perhaps combined with implementing a __del__ clean-up hook.

If you need to have your object cleaned up after a timeout, add your object to a global list, and remove it from that list when done playing. The list can be on the class itself:

class Playingsound:
    playing = []

    def fadeout_and_stop(self):
        Playingsound.playing.append(self)
        # do somthing (fadeout during 100 ms)
        Playingsound.playing.remove(self)

then if there are no other references to the instance Python will take care of cleaning it up for you:

a = Playingsound()
a.fadeout_and_stop()
del a

You can always access any sounds still playing via Playingsound.playing.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • thank you for your answer. I modified slightly the initial question, in order to make it more understandable. – Basj Dec 24 '13 at 09:31
  • Thank you! If I do `a.fadeout_and_stop()` and immediately, the next line : `del a`, there will be no time for the `fadeout` to be done, right ? – Basj Dec 24 '13 at 09:36
  • 1
    @Basj: You only removed the reference from `a`, but `Playingsound.playing` still holds a reference to the object, so object will not yet be deleted from memory. – Martijn Pieters Dec 24 '13 at 09:38
  • 1
    So if I sum the idea : I don't need to deal with such things, the garbage collector will do things for me ? i.e. the object will be deleted from memory once there is no more reference to it ? – Basj Dec 24 '13 at 09:46
  • 2
    @Basj: **Exactly**. Python takes care of cleanup *for you*. – Martijn Pieters Dec 24 '13 at 09:53
0

Just try to print self after "del self" statement in finish function,by doing this you will get error because of python memory management. After creating 'a' object to class A, this object 'a' will be tagged to some memory location, When you are calling finish() you are passing reference of 'a' object. So when u use del self just memory reference will be untagged to the object, But still our object is 'a' is pointing to that memory location. you need untag all references in order to destroy tha object.

Vb407
  • 1,577
  • 2
  • 15
  • 27
0

you can't destroy an object in python. It's the garbage collector's job. What you can do, is to change a reference to None or delete the reference. But if the object still has other links of reference, it will stay in the memory unharmed. Look at this example,

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
if __name__=='__main__':
    l1=ListNode(9)
    t=ListNode(8)
    l1.next=t
    l2=ListNode(1)
    s=Solution()
    r=s.addTwoNumbers(l1,l2)
    del t #not similar to t=None, this will fully destroy the existence
          #of the reference t, while t=None will only set the reference 
          #to None
    print l1.next.val #this will give the value 8
    print t #this line will give an error as reference t has no 
            #existence anymore

look the object that has a value 8 (created at the line, t=ListNode(8)) is still alive. We only destroyed the reference of t. But the actual object is at the hand of python's garbage collector. Only if we delete the other reference link (l1.next) then the object will lose all the reference links and will become an garbage and then python will destroy it completely from the memory. So while you have full control over the reference, you don't have control over the actual object.

Nasif Imtiaz Ohi
  • 1,563
  • 5
  • 24
  • 45