Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

self in python decorators

I want a decorator that would add the decorated function to list, like this :

class My_Class(object):

    def __init__(self):
        self.list=[]

    @decorator
    def my_function(self)
       print 'Hi'

I expect my_function to be added to self.list, but I just can't write this decorator. If I try to write it inside My_Class, then I would have to use @self.decorator, and self does not exist since we're outside any function. And if I try to write it out of My_Class, then I can't retrieve self from my_function.

I know quite similar questions exist, but they are overly complicated, and I'm just learning python and decorators.

like image 662
CGGJE Avatar asked Dec 04 '11 14:12

CGGJE


2 Answers

You can't access self from the decorator, because the decorator is run at the time the function is defined, and at that time there are no instances of My_Class yet.

It's better to put the function list as a class attribute instead of an instance attribute. Then you can pass this list as a parameter to the decorator:

def addToList(funcList):
    '''Decorator that adds the function to a given list'''
    def actual_decorator(f):
         funcList.append(f)
         return f
    return actual_decorator

class MyClass(object):
    funcList = []

    @addToList(funcList)
    def some_function(self, name):
        print 'Hello,', name

Now you can access MyClass.funcList to get the list of decorated functions.

like image 108
interjay Avatar answered Sep 23 '22 04:09

interjay


There's nothing really special about writing decorators for bound functions (instance methods). For example, this simple example works fine:

def decorator(fn):
    print "I'm decorating!"
    return fn


class MyClass(object):
    def __init__(self):
        self.list = []

    @decorator
    def my_function(self):
        print "Hi"

If you want to use self in your decorator, you'll treat your decorator the same as you'd treat any decorator that uses the function's args:

def decorator(fn):
    def _decorator(self):
        print "I'm decorating, and here's my list: %s!" % self.list
        return fn(self)
    return _decorator
like image 37
Adam Wagner Avatar answered Sep 22 '22 04:09

Adam Wagner