也许标题有点误导,但我想创建一个简单的装饰器来装饰一些类方法,因为"允许"在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
答案 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
...