Getting a code obj's function?

Alex Martelli aleaxit at yahoo.com
Fri Dec 15 06:59:54 EST 2000


"Bjoern Giesler" <un4e at rzstud1.rz.uni-karlsruhe.de> wrote in message
news:91co73$fpm$1 at news.rz.uni-karlsruhe.de...
> Hi,
>
> another inane question...
>
> ...is there a standard way to get the function object that a code object
is
> associated with? On exception, I only get the code object from the
> traceback.

Right.  It might not even belong to any function...


> If there is no standard way, could somebody please comment on the
following:
> I've modified my Python interpreter so that a code object has one more
> member, co_func. This gets set to None initially, and PyFunc_New() sets it
> to the new function object that is created. What are the potential
problems
> with this approach, if any? I see all kinds of memory leaks / double frees
> coming, but haven't really enough understanding of Python to know what
might

Circular reference -- if object F holds a reference to object C and
viceversa, neither is ever going to go away unless/until this is
explicitly broken (Python 2's GC may ameliorate this problem, though).

> happen. My assumption was that a code object is assigned to a maximum of
> exactly one function. Is this correct?

No; the func_code attribute is not read-only:

D:\PySym>python
Python 2.0 (#8, Oct 16 2000, 17:27:58) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> def f():
...   print 'f'
...
>>> def g():
...   print 'g'
...
>>> f()
f
>>> g()
g
>>> f.func_code = g.func_code
>>> f()
g
>>> g()
g
>>> ^Z

so a given code-object may belong to any number of functions -- from
0 on up.  (The 'new' module also lets you build a function using any
existing code-object).  Of course, this is not 'typical'!-)


Whenever you want to follow some existing reference 'backwards', you
are faced with several possible choices.  One is the one you've taken,
introducing a backwards-link, which, however, creates circularity
(which may or may not be a problem in a given case).  Another is
to use a 'weak' reference of some kind for the backwards-link (only
advantage, avoiding the unwontedly-keep-alive circularity).  These
choices share a weakness if the 'existing reference' are many-to-1,
as, 'in theory', is the F->C one in Python.

Depending on 'how _often_' you need to follow the back-way, a
practicable choice may be just to make sure you can always enumerate
all objects which 'might' be the one you're looking for -- e.g.,
all function-objects, in this case; the 'back-link' is then an
exhaustive search over all candidate objects, noting the ones
whose (forward) links satisfy your condition (a set with 0 to
whatever elements).  If enumerating _all_ candidates is not an
acceptable performance-hit, this strategy may sometimes be
tweaked to make performance satisfactory, e.g. by keeping the
objects in suitable 'bins' (you'd have to catch assignments to
func_code to change a function's bin -- not sure how easy or
hard that would be).


Alex






More information about the Python-list mailing list