views:

4681

answers:

8

Why won't this work? I'm trying to make an instance of a class delete itself.

>>> class A():
    def kill(self):
     del self


>>> a = A()
>>> a.kill()
>>> a
<__main__.A instance at 0x01F23170>
+20  A: 

'self' is only a reference to the object. 'del self' is deleting the 'self' reference from the local namespace of the kill function, instead of the actual object.

To see this for yourself, look at what happens when these two functions are executed:

>>> class A():
...     def kill_a(self):
...         print self
...         del self
...     def kill_b(self):
...         del self
...         print self
... 
>>> a = A()
>>> b = A()
>>> a.kill_a()
<__main__.A instance at 0xb771250c>
>>> b.kill_b()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in kill_b
UnboundLocalError: local variable 'self' referenced before assignment
yjerem
+12  A: 

You don't need to use del to delete instances in the first place. Once the last reference to an object is gone, the object will be garbage collected. Maybe you should tell us more about the full problem.

Ned Batchelder
A: 

Indeed, Python does garbage collection through reference counting. As soon as the last reference to an object falls out of scope, it is deleted. In your example:

a = A()
a.kill()

I don't believe there's any way for variable 'a' to implicitly set itself to None.

Cybis
A: 

I'm curious as to why you would want to do such a thing. Chances are, you should just let garbage collection do its job. In python, garbage collection is pretty deterministic. So you don't really have to worry as much about just leaving objects laying around in memory like you would in other languages (not to say that refcounting doesn't have disadvantages).

Although one thing that you should consider is a wrapper around any objects or resources you may get rid of later.

class foo(object):
    def __init__(self):
        self.some_big_object = some_resource

    def killBigObject(self):
        del some_big_object

In response to Null's addendum:

Unfortunately, I don't believe there's a way to do what you want to do the way you want to do it. Here's one way that you may wish to consider:

>>> class manager(object):
...     def __init__(self):
...             self.lookup = {}
...     def addItem(self, name, item):
...             self.lookup[name] = item
...             item.setLookup(self.lookup)
>>> class Item(object):
...     def __init__(self, name):
...             self.name = name
...     def setLookup(self, lookup):
...             self.lookup = lookup
...     def deleteSelf(self):
...             del self.lookup[self.name]
>>> man = manager()
>>> item = Item("foo")
>>> man.addItem("foo", item)
>>> man.lookup
 {'foo': <__main__.Item object at 0x81b50>}
>>> item.deleteSelf()
>>> man.lookup
 {}

It's a little bit messy, but that should give you the idea. Essentially, I don't think that tying an item's existence in the game to whether or not it's allocated in memory is a good idea. This is because the conditions for the item to be garbage collected are probably going to be different than what the conditions are for the item in the game. This way, you don't have to worry so much about that.

Jason Baker
A: 

I'm making a simple system of objects that can interact with each other for a game. One thing I want objects to do is to destroy themselves with a method.

class Generic:
    ''' Generic class all other classes inherit '''
    def kill(self):
        del self
        #Need a way to remove the instance of the class

class Item(Generic):
    def __init__(self,name):
        self.name = name

class Being(Generic):
    def __init__(self,name):
        self.name = name
        self.bag = []

    def pick_up(self,target):
        self.bag.append(target)
        target.kill()

player = Being('Hero')
print player

cat = Item('Cat')
print cat


print'Players inventory',player.bag

print'Picking up the cat'
player.pick_up(cat)

print'Players inventory',player.bag
You should keep in your mind two very separate things. One is "things getting killed in the game". And the second is "the programming language handling your objects". You should dela with the first one, and let python deal with the second.
Ali A
This additional detail should be part of the question. It's not an answer to the question. It's more of the question.
S.Lott
I added a bit in response to this here: http://stackoverflow.com/questions/293431/python-object-deleting-itself#293485
Jason Baker
+1  A: 

In this specific context, your example doesn't make a lot of sense.

When a Being picks up an Item, the item retains an individual existence. It doesn't disappear because it's been picked up. It still exists, but it's (a) in the same location as the Being, and (b) no longer eligible to be picked up. While it's had a state change, it still exists.

There is a two-way association between Being and Item. The Being has the Item in a collection. The Item is associated with a Being.

When an Item is picked up by a Being, two things have to happen.

  • The Being how adds the Item in some set of items. Your bag attribute, for example, could be such a set. [A list is a poor choice -- does order matter in the bag?]

  • The Item's location changes from where it used to be to the Being's location. There are probably two classes os Items - those with an independent sense of location (because they move around by themselves) and items that have to delegate location to the Being or Place where they're sitting.

Under no circumstances does any Python object ever need to get deleted. If an item is "destroyed", then it's not in a Being's bag. It's not in a location.

player.bag.remove(cat)

Is all that's required to let the cat out of the bag. Since the cat is not used anywhere else, it will both exist as "used" memory and not exist because nothing in your program can access it. It will quietly vanish from memory when some quantum event occurs and memory references are garbage collected.

On the other hand,

here.add( cat )
player.bag.remove(cat)

Will put the cat in the current location. The cat continues to exist, and will not be put out with the garbage.

S.Lott
Is this intended to be funny? I think it's pretty funny!
sep332
Schrodinger's cat lives! Or doesn't! That pesky Copenhagen Interpretation is so confusing. So's garbage collection.
S.Lott
does it make sense ? - is an religious question,what is happening ? - is the scientific question!
Blauohr
@Blauohr: Since I believe software must capture meaning, I'm making a religious judgement.
S.Lott
@S.Lott To be fair: It is good to answer both questions :-)
Blauohr
@Blauohr: Since I can't see a useful distinction between what is meant and what happens, If what happens is not what it means, then there's a bug, and we need to make what happens match what was meant. Deep analysis of what happens -- when that's a bug -- isn't helpful.
S.Lott
A: 

This is a very important aspect of programming, I don't understand why an object shouldn't self destruct. There should be an option for objects to self destruct depending on its interaction with other objects.

noireknight
A: 

I can't tell you how this is possible with classes, but functions can delete themselves.

def kill_self(exit_msg = 'killed'):
    global kill_self
    del kill_self
    return exit_msg

And see the output:

 >>> kill_self
<function kill_self at 0x02A2C780>
>>> kill_self()
'killed'
>>> kill_self
Traceback (most recent call last):
  File "<pyshell#28>", line 1, in <module>
    kill_self
NameError: name 'kill_self' is not defined

I don't think that deleting an individual instance of a class without knowing the name of it is possible.

NOTE: If you assign another name to the function, the other name will still reference the old one, but will cause errors once you attempt to run it:

>>> x = kill_self
>>> kill_self()
>>> kill_self
NameError: name 'kill_self' is not defined
>>> x
<function kill_self at 0x...>
>>> x()
NameError: global name 'kill_self' is not defined
Nathanael Abbotts
And now try this with calling kill_self from other module.
Daniel Kluev