这个简单的装饰工作符合预期:
def protect(*permissions):
def outer(f):
def inner(*args):
print permissions[0]
return f(*args)
return inner
return outer
@protect('protected')
def func(var):
return var
print func('something')
输出结果为:
protected
something
超越Python shell并在我项目的更大范围内使用装饰器,发生了一些奇怪的事情:在inner
函数内部,permissions
未定义。
我认为必须有一些Python变量作用域/装饰器细微之处,我不知道这可能导致这种情况。任何见解都表示赞赏。
答案 0 :(得分:1)
在我的脑海里,我可以弄明白发生了什么 - 让我试着拼出来:
它与Python有关,而不是“感知”“内部”函数之外的范围内存在的“权限”变量 - 因为当“内部”本身被定义时,“权限”将长期定义在'最外面的保护范围。因此,在编译inner
时,变量被视为全局变量。 (这就是为什么需要完全错误消息 - NameErrors可以用于定义之前使用的局部变量,或者用于不存在的全局变量 - 在这种情况下确切的消息会说明很多)
换句话说,你最有可能遇到一个实现错误 - 请尝试公开导致问题的最小代码和你正在使用的python版本。如果可能,请尝试使用最新的微型版本 - 十次是时候在bugs.python.org上打开一个问题
我看到两个解决方法 - 第一个是确认我的诊断的黑客 - 并且可能根本不起作用:对permissions
函数上的outer
变量进行读取访问,在inner
之外的身体:这应该使解释者将其“感知”为外部的非局部变量,并将其传播到内部。
另一种解决方法是更加可靠和一致 - 在这种情况下甚至可能更好的代码样式:在这种情况下使用类作为装饰器,而不是依赖于多个嵌套函数及其闭包。
以上代码段可以改写为:
class Protect(object):
def __init__(self, *permissions):
self.permissions = permissions
def __call__(self, f):
def inner(*args):
print self.permissions[0]
return f(*args)
return inner
@Protect('protected')
def func(var):
return var
print func('something')
此代码不依赖于嵌套闭包,因此避免指出您遇到的错误。此外,它遵循“扁平比嵌套更好”和“明确优于隐式”编码指南。
但请通过向我们提供实际触发此行为的版本和代码,帮助每个人追踪此错误,如果不是在python.org上打开问题
答案 1 :(得分:0)
我遇到过这个问题一次,原因是你无法设置一个放在闭包中的变量。不知道你是否属于这种情况,但很高兴知道。