gpt4 book ai didi

python - 在 Python 装饰器中丢失变量范围

转载 作者:太空宇宙 更新时间:2023-11-03 19:32:29 25 4
gpt4 key购买 nike

这个简单的装饰器按预期工作:

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变量作用域/装饰器的微妙之处,我不知道这可能会导致这种情况。任何见解都值得赞赏。

最佳答案

在我的脑海中,我可以弄清楚发生了什么 - 让我尝试将其拼写出来:

这与Python没有“感知”“权限”变量存在于“内部”函数之外的范围有关 - 因为当“内部”本身被定义时,“权限”早就在“内部”函数中定义了。最外面的保护范围。因此,在编译inner时,variale被视为全局变量。 (这就是为什么需要准确错误消息 - NameErrors 可以针对定义之前使用的局部变量,也可以针对不存在的全局变量 - 在这种情况下,准确的消息会告诉你很多信息)

换句话说,您很可能遇到了实现错误 - 请尝试公开导致问题的最小代码量以及您正在使用的确切 python 版本。如果可能的话,请尝试使用您可用的最新微型版本 - 十是时候在 bugs.python.org 上提出问题

我看到两种解决方法 - 第一个是可以确认我的诊断的黑客攻击 - 并且可能根本不起作用:对 outer 上的 permissions 变量进行读取访问 函数,在 inner 的主体之外:这应该使解释器将其“感知”为outer中的非局部变量,并将其传播到inner中。

另一种解决方法更加可靠和一致 - 在这种情况下,对于 yu 来说甚至可能有更好的代码样式:在这种情况下使用类作为装饰器,而不是依赖于多个嵌套函数及其闭包。

上面的代码片段可以重写为:

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 上提出问题,请向我们提供实际触发此行为的版本和代码,帮助大家追踪此错误

关于python - 在 Python 装饰器中丢失变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5096765/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com