views:

57

answers:

2

For example, if I'm decorating a method like so

def my_decorator(fn):

    # Do something based on the class that fn is a method of

    def decorated_fn(*args, **kwargs):
        fn(*args, **kwargs)

    return decorated_fn

class MyClass(object):

    @my_decorator
    def my_method(self, param):
        print "foo"

Is it possible in my_decorator to determine where fn came from?

A: 

No. You'll have to defer it until decorated_fn() is called.

Ignacio Vazquez-Abrams
+3  A: 

Short answer: No.

Longer answer: You can do it by mucking about in the stack trace (see the inspect module) but it's not a great idea.

Full answer: At the time the function gets decorated, it's still an unbound function. Try the following:

def my_dec(fn):
    print dir(fn) # Has "func_code" and "func_name"
    return fn

class A(object):
    @my_dec
    def test(self):
        pass

print dir(A.test) # Has "im_class" and "im_self"

You can see that the raw function gets passed to the decorator, while the bound function is available after the class is declared.

The way to accomplish this is to just the function decorator in conjunction with either a metaclass or a class decorator. In either case, the function decorator can set a flag on the function, and the metaclass or class decorator can look for it and do the appropriate thing.

Chris B.