Removing objects

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Jan 23 12:55:11 CET 2008


On Tue, 22 Jan 2008 22:59:07 -0800, bladedpenguin wrote:

> I am writing a game, and it must keep a list of objects. I've been
> representing this as a list, but I need an object to be able to remove
> itself. It doesn't know it's own index. If I tried to make each object
> keep track of it's own index, it would be invalidated when any object
> with a lower index was deleted.  The error was that when I called
> list.remove(self), it just removed the first thing in hte list with the
> same type as what I wanted, rather than the object I wanted. The objects
> have no identifying charachteristics, other than thier location in
> memory
> 
> So my question: How do I look something up in a list by it's location in
> memory? does python even support pointers?

That's the wrong question. It wouldn't even help you solve your problem. 

Example:

alist = [object1, object2, object3, object4]

object3 is at location 0xb7d27df4 in memory. Now how do you delete it 
from alist?


You say that list.remove(self) "just removed the first thing in the list 
with the same type" -- that suggests a bug in your code, not in remove(). 
Perhaps "self" isn't what you think it is?

Here's how it should work:

class MyClass(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return "<%s>" % self.name
    def delete_me(self, alist):
        alist.remove(self)

obj1 = MyClass("Fred")
obj2 = MyClass("Betty")
obj3 = MyClass("Jill")
alist = [obj1, obj2, obj3]


Now let's see it in action:


>>> alist
[<Fred>, <Betty>, <Jill>]
>>> obj3.delete_me(alist)  # tell obj3 to delete itself from the list
>>> alist
[<Fred>, <Betty>]


Works fine.

But what you can't do is create a NEW object, one that isn't in the list 
but just looks similar, and expect it to be removed:

>>> MyClass("Fred").delete_me(alist)  # a different "Fred".
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in delete_me
ValueError: list.remove(x): x not in list


For that to work, you need to give your class an __eq__ method, and have 
it match by name:

    # put this in MyClass
    def __eq__(self, other):
        return self.name == self.other



Now any instance MyClass("Fred") is equal to any other MyClass("Fred"), 
and remove will work 



> Is there a better way?


You might also consider using a dictionary instead of a list.



-- 
Steven



More information about the Python-list mailing list