Search code examples
pythonpython-2.7python-decorators

Python class not in globals when using decorator


Maybe the title is a bit misleading, however I wanted to create a simple decorator to decorate some class methods as "allowed" in an RPC mechanism, but I'm stuck on a strange error when trying to access class variables (Python 2.7.5). Check the code below:

class myclass():

    rpcallowedmethods = []

    def __init__(self):            
        pass

    def rpcenabled(fn):
        print fn
        print globals()
        print myclass

    @rpcenabled
    def somefunc(self,param):
        pass

c = myclass()

Exception: NameError: global name 'myclass' is not defined

Anyone can explain the reason behind this to me?

EDIT: What I'm asking is more about the fact that python executes the decorator defined in a class and run against decorated classmethods even prior having the class in the globals, so I believed it's more of a logical "bug" in the python implementation than a seemingly obvious NameError


Solution

  • The actual class object is only assigned to its name after its definition is finished. Thus you cannot use the class name during its definition. You can either create a decorator outside of the class to which you explicitly pass the list you want to fill, or use the following:

    class myclass():
        rpcmethods = []
    
        def _rpcallowed(fct, l=rpcmethods):
            l.append(fct)
            return fct
    
        @_rpcallowed
        def myfct(): pass
    

    Note that the default parameter (l=rpcmethods) is a workaround as you cannot access a class variable inside of a function without a reference to the class or an instance.

    The variant with the decorator outside of the class would probably qualify as being "cleaner" than this as it's explicit and reusable, but it would be a bit more code and less specific.