Is it possible to delete an instance of a class that automatically removes it from all lists in which it is an element?

StackOverflow https://stackoverflow.com/questions/22568690

Frage

I have an instance of a class which appears as an element in multiple lists. I want to delete the instance and simultaneously remove it from every list in which it is an element. Is this possible?

War es hilfreich?

Lösung

One answer to this is to always allow the objects that you are putting into the lists to manage list membership. For example, rather than saying

listA.append(objectA)

you would use

objectA.addToList(listA)

This would allow you to internally store a list of all list that contain objectA. Then, when you want to delete objectA, you need to call a method like this:

def cleanup(self):
    for listToClean in myLists:
        listToClean.remove(self)

This does put some strong limitations on your program though - for example, if a copy is made of one of these lists, then the objects will not have a reference to that copy. You have to work with the assumption that any copy of a list (don't forget that slices are copies, too) may have obsolete objects in it, which would mean that you would want to be working with the original lists as frequently as possible.

Andere Tipps

You might consider using weakref.refs:

class WeakRefList(list):
    def __init__(self, args):
        list.__init__(self, [self.weak(item) for item in args])
    def append(self, item):
        list.append(self, self.weak(item))
    def weak(self, item):
        return weakref.ref(item, self.remove)

class Object(object):
    def __init__(self, name):
        self.name = name

orig = [Object('Foo'), Object('Bar')]
weaklist = WeakRefList(orig)
orig.append(Object('Baz'))
weaklist.append(orig[-1])
print(orig[0])
# <__main__.Object object at 0xb748aaac> 
print(weaklist)
# [<weakref at 0xb7487a54; to 'Object' at 0xb748aaac>,
#  <weakref at 0xb7487a7c; to 'Object' at 0xb748ab6c>,
#  <weakref at 0xb7487aa4; to 'Object' at 0xb748ac2c>]

You call the weakref to recover the original object. If it does not exist, calling the wearef returns None:

print(weaklist[0]())
# <__main__.Object object at 0xb748aaac>

It returns exactly the same object:

print(orig[0] is weaklist[0](), id(orig[0]), id(weaklist[0]()))
# (True, 3074992812L, 3074992812L)

You can access its attributes (or methods) as usual:

print(weaklist[0]().name)
# Foo

for item in weaklist:
    print(item)
    # <weakref at 0xb7487a54; to 'Object' at 0xb748aaac>
    # <weakref at 0xb7487a7c; to 'Object' at 0xb748ab6c>
    # <weakref at 0xb7487aa4; to 'Object' at 0xb748ac2c>

print([item.name for item in orig])
# ['Foo', 'Bar', 'Baz']
print([item().name for item in weaklist])
# ['Foo', 'Bar', 'Baz']

And finally, here's the property you are seeking: deleting items from orig automatically deletes them from weaklist as well:

while orig:
    item = orig.pop()
    del item
print(orig)        
# []
print(weaklist)
# []
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top