Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Introspecting a given function's nested (local) functions in Python

Given the function

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'

is there a way for me to access its local get() and post() functions in a way that I can call them? I'm looking for a function that will work like so with the function f() defined above:

>>> get, post = get_local_functions(f)
>>> get()
'get'

I can access the code objects for those local functions like so

import inspect
for c in f.func_code.co_consts:
    if inspect.iscode(c):
        print c.co_name, c

which results in

get <code object get at 0x26e78 ...>
post <code object post at 0x269f8 ...>

but I can't figure out how to get the actual callable function objects. Is that even possible?

Thanks for your help,

Will.

like image 573
Will McCutchen Avatar asked Aug 05 '09 17:08

Will McCutchen


People also ask

How do you call a nested function in Python?

A function defined inside another function is called a nested function. Nested functions can access variables of the enclosing scope. In Python, these non-local variables are read-only by default and we must declare them explicitly as non-local (using nonlocal keyword) in order to modify them.

Can you have nested functions in Python?

Inner functions, also known as nested functions, are functions that you define inside other functions. In Python, this kind of function has direct access to variables and names defined in the enclosing function. Inner functions have many uses, most notably as closure factories and decorator functions.

How do you call nested functions?

You must call a nested function either directly by name (without using feval ), or using a function handle that you created using the @ operator (and not str2func ). All of the variables in nested functions or the functions that contain them must be explicitly defined.

Can a nested function access outer variable?

Nested functionsIt can access the outer variables and so can return the full name.


2 Answers

You are pretty close of doing that - just missing new module:

import inspect
import new

def f():
    x, y = 1, 2
    def get():
        print 'get'
    def post():
        print 'post'

for c in f.func_code.co_consts:
    if inspect.iscode(c):
        f = new.function(c, globals())
        print f # Here you have your function :].

But why the heck bother? Isn't it easier to use class? Instantiation looks like a function call anyway.

like image 93
gavoja Avatar answered Oct 06 '22 01:10

gavoja


You can return functions just like any other object in Python:

def f():
    x, y = 1, 2 
    def get():
        print 'get'
    def post():
        print 'post'
    return (get, post)


get, post = f()

Hope this helps!

Note, though, that if you want to use your 'x' and 'y' variables in get() or post(), you should make them a list.

If you do something like this:

def f():
    x = [1]
    def get():
        print 'get', x[0]
        x[0] -= 1
    def post():
        print 'post', x[0]
        x[0] += 1
    return (get, post)

get1, post1 = f()
get2, post2 = f()

get1 and post1 will reference a different 'x' list than get2 and post2.

like image 39
rledley Avatar answered Oct 06 '22 00:10

rledley