Magic function

Rüdiger Werner larudwer at freenet.de
Sun Jan 13 14:04:23 CET 2008


Well as I understand your problem now,
you would not like all instances of an specific object that are still alive,
but all references to an object (created somewhere, sometimes) in an local
context (stack frame),
that are accessible from 'that' context ( but also from many others).

However in python a stack frame does not 'contain' an object. It only
contains a reference to an
object. You may delete this reference whithin this frame, but the object may
still be alive.

So you can do following:

def run(att):
    for k, v in att.iteritems():
        if isinstance(v, dict):
            print k, v, id(v)

def foo(bar):
    x = list()
    y = object()
    run(locals())
    del bar
    run(locals())

bazz = dict()
print "bazz has id ", id(bazz)
foo(bazz)
print "bazz has id ", id(bazz)

>pythonw -u "console_play.py"
bazz has id  11068592
bar {} 11068592
bazz has id  11068592
>Exit code: 0

Note that bar {} is printed only once, since the reference 'bar' defined in
foo has been deleted. The object itself is still alive
because the referece 'bazz' still exists. You should consider, that
inspecting the stack will not tell you if an object is alive or not.
It also doesn't tell you that an object can't be used by your users. If you
come from an C++ background, then consider that python
is different. Creating an object in an local context will not destroy this
object if you leafe this context.
There is no such thing like a 'destructor' in python. You should also
consider, that frame objects are not destroyed if used by an
generator or if there is still a reference to them. A frame object may life
forever. Read the manual about the inspect module!

Inspecting the stack may give you wrong and difficult to debug results. I
just wouldn't do that.
Keeping track of instances isn't that difficult.

However if  you need instances (not references to them!) that have been
created within a specific stack frame
you may use my example below. It will extend the weakref with the id of the
stackframe that created it. However
the instance may still live while the frame had been destroyed long ago!

Remember:
Inspecting the stack will not tell you weather a user can use an specific
object nor will it tell you, if the object is alive or not.


from weakref import ref
from inspect import getouterframes, currentframe

class ExtendedRef(ref):
    def __init__(self, ob, callback=None, **annotations):
        super(ExtendedRef, self).__init__(ob, callback)
        self.__id = 0

class WeakSet(set):
    def add(self, value, id=0):
        wr = ExtendedRef(value, self.remove)
        wr.__id = id
        set.add(self, wr)
    def get(self, id):
        return [ _() for _ in self if _.__id == id]

class bigobject(WeakSet):
    def run(self):
        outer_frame = id(getouterframes( currentframe())[1][0])
        for obj in self.get(outer_frame):
            # process object's
            print obj.value

class foo(object):
    __instances__ = bigobject()
    def __init__(self, value):
        outer_frame = id(getouterframes( currentframe())[1][0])
        foo.__instances__.add(self, outer_frame)
        self.value = value


def main( depth ):
    obj1 = foo("obj1 at depth %s" % depth)
    obj2 = foo("obj2 at depth %s" % depth)
    foo.__instances__.run()
    print "processed objects created at %s" % id(currentframe())
    if depth == 0:
        return
    else:
        main(depth-1)

if __name__ == "__main__":
    obj1 = foo("obj1 at depth root")
    main(3)
    foo.__instances__.run()
    print "processed objects created at %s" % id(currentframe())


>pythonw -u "test12.py"
obj1 at depth 3
obj2 at depth 3
processed objects created at 11519672
obj2 at depth 2
obj1 at depth 2
processed objects created at 11496496
obj2 at depth 1
obj1 at depth 1
processed objects created at 11813904
obj2 at depth 0
obj1 at depth 0
processed objects created at 11814272
obj1 at depth root
processed objects created at 11443120
>Exit code: 0












More information about the Python-list mailing list