0

If I wanted to use a decorator as follows:

@getFunc('bar')
def foo():
    def bar():
        print 'bar'

How would I make the decorator retrieve the inner function named bar?

def getFunc(str)
    def getFunc_inner(func):
        def new(*args, **kwargs):
            func(*args, **kwargs)
            myFunc = ??# Get function named {str} from func
        return new
    return getFunc_inner
alko
  • 46,136
  • 12
  • 94
  • 102
grivescorbett
  • 1,605
  • 1
  • 21
  • 29
  • I think one way would be to use the `inspect` and `ast` modules. – Paul Draper Nov 09 '13 at 21:00
  • short answer: you can't – alko Nov 09 '13 at 23:58
  • 1
    possible duplicate of [How to get/set local variables of a function (from outside) in Python?](http://stackoverflow.com/questions/1360721/how-to-get-set-local-variables-of-a-function-from-outside-in-python) – alko Nov 10 '13 at 00:02

2 Answers2

0

you can return the function like this:

from functools import wraps
def method_decorator(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        res =  fn(*args,**kwargs)
        if callable(res):
            return res()
        return res
    return wrapper

@method_decorator
def foo( *args, **kwargs):
    def baz():
        return "foo"
    return baz

@method_decorator
def bar( *args, **kwargs):
    return("bar")

if __name__ == "__main__":
    print(foo())
    print(bar())

prints:

foo
bar
Foo Bar User
  • 2,401
  • 3
  • 20
  • 26
0

A decorator cannot, and does not "retrieve" a function. A decorator is a function which takes a function (the decorated function), and returns another function (the result of the decorating process).

If the wrapped function were to return its inner function, then the function created by the decorator could do anything it liked with that.

Given a function object, can I retrieve a function defined within that object by name?

No, because a def statement is an executable statement. You are confused by the static appearance of the function text. Until the outer function is invoked, there is no inner function object for you to access. This is necessarily so, as the inner function object closes over the variables (context) of the invocation of the outer function. Or to put it more simply, in the following code, the two functions returned1 and returned2 are different functions:

def outer(x):
    def inner(y):
        return x+y
    return inner

returned1 = outer(2)
returned2 = outer(2)
Marcin
  • 48,559
  • 18
  • 128
  • 201
  • The fact that it is a decorator is actually immaterial in this case. I suppose the proper question would be: Given a function object, can I retrieve a function defined within that object by name? I suppose I could get the AST of the text of the function, but that seems like overkill. – grivescorbett Nov 10 '13 at 01:22
  • @grivescorbett It's only irrelevant if you want to completely ignore all principles of style and design. Anyway, the answer to your question is that you can't. See my edited answer for details. – Marcin Nov 10 '13 at 01:23