Removing objects

Robert Kern robert.kern at gmail.com
Wed Jan 23 02:24:17 EST 2008


bladedpenguin at gmail.com 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

By default, classes that do not implement the special methods __eq__ or __cmp__ 
get compared by identity; i.e. "(x == y) == (x is y)". Double-check your classes 
and their super-classes for implementations of one of these methods. 
mylist.remove(x) will check "x is mylist[i]" first and only check "x == 
mylist[i]" if that is False.


In [1]: class A(object):
    ...:     def __eq__(self, other):
    ...:         print '%r == %r' % (self, other)
    ...:         return self is other
    ...:     def __ne__(self, other):
    ...:         print '%r != %r' % (self, other)
    ...:         return self is not other
    ...:
    ...:

In [2]: As = [A() for i in range(10)]

In [3]: As
Out[3]:
[<__main__.A object at 0xf47f70>,
  <__main__.A object at 0xf47d90>,
  <__main__.A object at 0xf47db0>,
  <__main__.A object at 0xf47cb0>,
  <__main__.A object at 0xf47eb0>,
  <__main__.A object at 0xf47e70>,
  <__main__.A object at 0xf47cd0>,
  <__main__.A object at 0xf47e10>,
  <__main__.A object at 0xf47dd0>,
  <__main__.A object at 0xf47e90>]

In [4]: A0 = As[0]

In [5]: A0
Out[5]: <__main__.A object at 0xf47f70>

In [6]: As.remove(A0)

In [7]: As
Out[7]:
[<__main__.A object at 0xf47d90>,
  <__main__.A object at 0xf47db0>,
  <__main__.A object at 0xf47cb0>,
  <__main__.A object at 0xf47eb0>,
  <__main__.A object at 0xf47e70>,
  <__main__.A object at 0xf47cd0>,
  <__main__.A object at 0xf47e10>,
  <__main__.A object at 0xf47dd0>,
  <__main__.A object at 0xf47e90>]

In [8]: A0
Out[8]: <__main__.A object at 0xf47f70>

In [9]: A9 = As[-1]

In [10]: As.remove(A9)
<__main__.A object at 0xf47d90> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47db0> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47cb0> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47eb0> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47e70> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47cd0> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47e10> == <__main__.A object at 0xf47e90>
<__main__.A object at 0xf47dd0> == <__main__.A object at 0xf47e90>

In [11]: As
Out[11]:
[<__main__.A object at 0xf47d90>,
  <__main__.A object at 0xf47db0>,
  <__main__.A object at 0xf47cb0>,
  <__main__.A object at 0xf47eb0>,
  <__main__.A object at 0xf47e70>,
  <__main__.A object at 0xf47cd0>,
  <__main__.A object at 0xf47e10>,
  <__main__.A object at 0xf47dd0>]

In [12]: A9
Out[12]: <__main__.A object at 0xf47e90>


If you cannot find an implementation of __eq__ or __cmp__ anywhere in your code, 
please try to make a small, self-contained example like the one above but which 
demonstrates your problem.

> So my question: How do I look something up in a list by it's location
> in memory? does python even support pointers?

If you need to keep an __eq__ that works by equality of value instead of 
identity, then you could keep a dictionary keyed by the id() of the object. That 
will correspond to its C pointer value in memory.

In [13]: id(A9)
Out[13]: 16023184

In [14]: hex(_)
Out[14]: '0xf47e90'

> Is there a better way?

Possibly. It looks like you are implementing a cache of some kind. Depending on 
exactly how you are using it, you might want to consider a "weak" dictionary 
instead. A weak dictionary, specifically a WeakValueDictionary, acts like a 
normal dictionary, but only holds a weak reference to the object. A weak 
reference does not increment the object's reference count like a normal 
("strong") reference would. Consequently, once all of the "strong" references 
disappear, the object will be removed from the WeakValueDictionary without your 
having to do anything explicit. If this corresponds with when you want the 
object to be removed from the cache, then you might want to try this approach. 
Use "id(x)" as the key if there is no more meaningful key that fits your 
application.

   http://docs.python.org/lib/module-weakref.html

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco




More information about the Python-list mailing list