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