Removing objects

bladedpenguin at gmail.com bladedpenguin at gmail.com
Wed Jan 23 07:13:21 EST 2008


On Jan 23, 2:24 am, Robert Kern <robert.k... at gmail.com> wrote:
> bladedpeng... 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

So, in general, is it more efficient to use a dictionary or to
override the __eq__ function?



More information about the Python-list mailing list