使用装饰器时,Python类不在全局变量中

时间:2014-11-06 13:55:21

标签: python python-2.7 python-decorators

也许标题有点误导,但我想创建一个简单的装饰器来装饰一些类方法,因为"允许"在RPC机制中,但我在尝试访问类变量时遇到了一个奇怪的错误(Python 2.7.5)。检查以下代码:

class myclass():

    rpcallowedmethods = []

    def __init__(self):            
        pass

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

    @rpcenabled
    def somefunc(self,param):
        pass

c = myclass()

例外:NameError: global name 'myclass' is not defined

任何人都可以向我解释这背后的原因吗?

编辑: 我要问的更多的是python执行类中定义的装饰器并且在装饰的类方法中运行,即使之前在全局中有类,所以我认为它更像是一个逻辑&#34 ;错误"在python实现中比看似明显的NameError

3 个答案:

答案 0 :(得分:1)

在定义完成后,实际的类对象仅分配给其名称​​。因此,在定义期间不能使用类名。您可以在明确传递要填充的列表的类之外创建装饰器,也可以使用以下内容:

class myclass():
    rpcmethods = []

    def _rpcallowed(fct, l=rpcmethods):
        l.append(fct)
        return fct

    @_rpcallowed
    def myfct(): pass

请注意,默认参数(l=rpcmethods)是一种解决方法,因为您无法在不引用类或实例的情况下访问函数内部的类变量。

该类的装饰的变体可能有资格成为"更清洁"比这更明确和可重复使用,但它会有更多的代码和更少的具体。

答案 1 :(得分:1)

你在滥用装饰者。装饰器是为了给东西对象添加东西。以某种方式“装饰”它。

更常用的方法是装饰方法和类。元类是解决这个问题的另一种方法。它们更强大,但对你当前的问题来说太过分了。但是,您可能需要直接修改功能。并且在进行代理时保存整理rpc函数。

from types import FunctionType

def enable_rpc(func):
    func.rpc_enabled = True
    return func

def rpc_enabled_class(cls):
    functions = [attr for attr in vars(cls).values() 
        if isinstance(attr, FunctionType)]
    cls._rpc_enabled_methods = [
        func for func in functions
            if getattr(func, "rpc_enabled", False)
    ]
    return cls

@rpc_enabled_class
class SampleClass(object):

    @enable_rpc
    def my_func(self):
        pass

print(SampleClass._rpc_enabled_methods)

答案 2 :(得分:0)

奇怪的错误?

print myclass

导致错误。您无法在其定义中使用名称myclass ...