views:

44

answers:

4

This problem is thus: I have an instance of a class, I want to know what list it is a part of, i.e. :

class test_class() :
    def test() :
        print 'I am a member of list', parent_list

foo = [test_class(), 52, 63]
bar = ['spam', 'eggs']
foo[0].test()

I would like to print out I am a member of list foo. There are an arbitrary number of lists that any given instance of test_class() could belong to.

A: 

Since lists have no names, this is not possible directly. You have to put the lists in some container which can remember the names, for example a class:

class container(object):
    def locate(self, thing):
        for name, member in self.__dict__:
            if type(member) == type([]) and thing in member:
                print 'Found it in',name
                return
        print 'Sorry, nothing found'

c = container()
c.foo = [test_class(), 52, 63]
c.bar = ['spam', 'eggs']
Aaron Digulla
A: 

You could use the globals() function to find all the currently defined global symbols, filter this to find all the lists and then check if the item is in them.

>>> class test_class():
...     def test(self):
...         print "I am a member of the following lists", \
...             [name for (name,value) in globals().items() if isinstance(value,list) and self in value]
...
>>> foo = [test_class(), 52, 63]
>>> bar = ['spam', 'eggs']
>>> foo[0].test()
I am a member of the following lists ['foo']
Dave Webb
+1  A: 

First of all, I don't know what could be the use-case for it, because ideally while putting objects in list, you can track them via a dict or even if you have list of all lists you can just check for objects in them, so a better design wouldn't need such search.

So lets suppose for fun we want to know which lists a object is in. We can utilize the fact that gc knows about all objects and who refers to it, so here is a which_list function which tells which lists refer to it ( that necessarily doesn't mean it contains it)

import gc

class A(object): pass
class B(A): pass

def which_list(self):
    lists_referring_to_me = []
    for obj in gc.get_referrers(self):
        if isinstance(obj, list):
            lists_referring_to_me.append(obj)

    return lists_referring_to_me


a = A()
b = B()
foo = [a, 52, b]
bar = ['spam', b]

print which_list(a)
print which_list(b)

output:

[[<__main__.A object at 0x00B7FAD0>, 52, <__main__.B object at 0x00B7FAF0>]]
[[<__main__.A object at 0x00B7FAD0>, 52, <__main__.B object at 0x00B7FAF0>], ['spam', <__main__.B object at 0x00B7FAF0>]]
Anurag Uniyal
A: 

You can find all the lists that contain the object pretty easily, but it sounds like you are approaching this problem in entirely the wrong way. You would be much better to record in the instances a reference back to the lists that contain those objects.

However, since you ask, here's a literal answer to your question:

>>> import gc
>>> class test_class():
    def test(self):
        lists = [l for l in gc.get_referrers(self) if isinstance(l, list)]
        print('I am in lists at ' + ','.join(str(id(l)) for l in lists))


>>> foo = [test_class(), 52, 63]
>>> bar = ['spam', 'eggs']
>>> foo[0].test()
I am in lists at 18704624

Note that of course you can find the lists, but that doesn't tell you any of the names that might be being used to reference those lists. If you need names then wrap the lists in a class which has a name and add back references to the containing classes from each test_class instance.

Duncan