简体   繁体   中英

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.

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.

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

Your list attribute should be a class attribute (and it should be renamed, because list is a builtin type). Then you can do something like this:

my_methods = []

def my_method(method):
    my_methods.append(method)
    return method


class MyClass(object):

    my_methods = my_methods

    @my_method
    def my_function(self):
       print 'Hi'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM