getting the current function

G

Gary Robinson

Alex Martelli has a cookbook recipe, whoami, for retrieving the name of the current function: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66062. It uses sys._getframe(). I'm a little wary about using sys._getframe() because of the underscore prefix and the fact that the python docs say "This function should be used for internal and specialized purposes only."

I feel more comfortable using the equivalent functionality in the inspect module.

Also, I wanted a way to get access to the current function, not just its name.

I came up with:

import inspect

def thisfunc(n=0):
currentFrame = inspect.currentframe()
outerFrames = inspect.getouterframes(currentFrame)
callingFrame = outerFrames[n + 1][0]
callersCallingFrame = outerFrames[n + 2][0]
return callersCallingFrame.f_locals[callingFrame.f_code.co_name]

The n argument lets you go up the stack to get callers of callers if that's convenient. For instance:

def attr(name, value):
caller = thisfunc(1)
if not hasattr(caller, name):
setattr(caller, name, value)

def x():
attr('counter', 0)
thisfunc().counter += 1
print thisfunc().counter

x()
x()
x()

Returns the output

1
2
3

Of course you don't need an attr() function for creating a function attribute, but this way your code won't break if you change the name of the function.

I was about to create a cookbook recipe, but decided to ask for some feedback from the community first.

Do you see situations where this function wouldn't work right?

Also, the python docs warn about storing frame objects due to the possibility of reference cycles being created (http://docs.python.org/lib/inspect-stack.html). But I don't think that's a worry here since thisfunc() stores the references on the stack rather than the heap. But I'm not sure. Obviously, it would be easy to add a try/finally with appropriate del's, but I don't want to do it if it's not necessary.

I welcome feedback of any type.

Thanks,
Gary




--

Gary Robinson
CTO
Emergent Music, LLC
(e-mail address removed)
207-942-3463
Company: http://www.goombah.com
Blog: http://www.garyrobinson.net
 
J

Jonathan Gardner

I welcome feedback of any type.

This all seems a bit too complicated. Are you sure you want to do
this? Maybe you need to step back and rethink your problem.

Your example can be rewritten a number of different ways that are
easier to think about.

The simple approach:

_x_counter = 0
def x():
_x_counter += 1
return _x_counter

The generator approach:

def counter_gen():
x = 0
while True:
x += 1
yield x

counter = counter_gen()
counter.next()
counter.next() # etc...

A class-based approach:

class Counter(object):
def __init__(self):
self._x = 0

def count(self):
self._x += 1
return self._x

In general, there really isn't a need to mess with stack frames unless
you are really interested in looking at the stack frame.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top