我有一些测试代码:
def num(num): def deco(func): def wrap(*args, **kwargs): inputed_num = num return func(*args, **kwargs) return wrap return deco @num(5) def test(a): return a + inputed_num print test(1)
运行此代码时,我收到一个错误,显示未定义“inputed_num”
我的问题是:在wrap函数中,func是否可以得到“inputed_num”的闭包?
无论如何,如果没有,我应该如何实现我的目标:初始化一些值,并在主函数中直接使用这个值。
思考。
正如@Raymond所说的那样,定义函数后应用装饰器。这意味着,在编译函数体本身时,Pythn会看到inputed_num
变量,当它不是本地定义的变量时,它会生成代码以尝试将其作为全局变量访问。
这意味着您可以在decorator中对其进行变通:decorator可以在函数globals()空间中使用所需的名称设置一个全局变量,然后调用该函数。它应在单线程代码中可靠工作:
def num(num):
def deco(func):
def wrap(*args, **kwargs):
glob = func.func_globals
marker = object()
original_value = glob.get("inputed_num", marker)
glob["inputed_num"] = num
result = func(*args, **kwargs)
if original_value is marker:
del glob["inputed_num"]
else:
glob["inputed_num"] = original_value
return result
return wrap
return deco
@num(5)
def test(a):
return a + inputed_num
和:
>>> print test(1)
6
我的问题是:在wrap函数中,func是否可以得到“inputed_num”的闭包?
抱歉,这不是装修工的工作方式。它们在函数最初定义后得到应用。到那时,已经太晚了。
当你写:
@num(5)
def test(a):
return a + inputed_num
这相当于:
def test(a):
return a + inputed_num
test = num(5)(test) # note that num(5) is called after test() is defined.
为了实现你的目标,让inputed_num成为第一个要测试的论点。然后,让你的装修师通过这个论点:
def num(num):
def deco(func):
def wrap(*args, **kwargs):
inputed_num = num
return func(inputed_num, *args, **kwargs) # this line changed
return wrap
return deco
@num(5)
def test(inputed_num, a): # this line changed
return a + inputed_num
@num(6)
def test2(inputed_num, a):
return a + inputed_num
print test(10) # outputs 15
print test2(10) # outputs 16
希望能为你扫清一切:-)
不,没有那样的结局。函数可以关闭周围词法上下文中的变量,而不是调用上下文中的变量。换句话说,如果您实际在另一个函数中写入一个函数,那么内部函数可以访问外部函数中的变量:
def f():
g = 2
def f2():
print g
f2()
但是函数永远不能访问调用它们的函数内部的变量。
一般来说,没有办法做你想做的事情,即在函数外部设置任意变量。最接近的是,您可以在装饰器中使用全局inputed_num
将inputed_num
分配为全局变量。然后test
将访问全局值。
def num(num):
def deco(func):
def wrap(*args, **kwargs):
global outsider
outsider = num
return func(*args, **kwargs)
return wrap
return deco
@num(5)
def test(a):
print a+outsider
>>> test(2)
7
当然,变量设置是全局的,因此多个并发使用(例如递归)将不起作用。(只是为了好玩,你也可以在这里看到一个非常神秘的方法来做这件事,但它太疯狂了,在现实世界中没有用处。)
我安装了两个python3.8,其中一个在终端中具有sudo权限时使用,另一个在没有权限时使用: 安装了一个python3.8(我想根据我使用的软件): 和为spyder安装的python3.8 我需要anaconda3/bin/python3.8用于一个项目,但现在我想安装一个我必须自己构建的包到python3.8,我花了几天时间才意识到sudo哪个python3.8和哪个python3.8是不
我有一个类有很多静态方法与龙卷风协程装饰。我想添加另一个装饰器,捕捉异常并将它们写入文件: 但是,它不适用于装饰器: 我知道,Tornado使用了的方法,这可能是基于异常的,也许它会以某种方式阻止其他装饰程序的尝试捕获。。。那么,我如何使用我的装饰器来处理Tornado协同程序的异常呢? 多亏了Martijn Pieters,我的代码得以运行: 所以,我只需要指定Tornado。我试图将装饰器添加
我正在运行Ubuntu 18.04。 我使用mysql连接器-python连接Python到MySQL。 我使用的是Python 3.6.7,并且已经安装了mysql连接器-python。 我已经安装了mysql连接器-python-py3_8.0.13-1ubuntu18.10_all.deb. 在运行Python脚本时,mysql。连接器模块似乎加载正确,但脚本在碰到光标时失败。next()具
假设我有一些资源,我想在用python编写的aws lambda中的不同请求之间共享。我应该如何实现这一点? 是否有“启动后”挂钩,或者我应该在第一次调用时惰性地创建资源?“延迟初始化”的缺点是,它意味着一些请求会随机变慢,因为您选择了一个消费者来承担启动成本。 此外…这些资源会在lambda可执行文件被“冻结”后幸存下来吗? 本页https://docs.aws.amazon.com/lambd
我需要在我的中添加一个新的目录位置,但问题是我使用的是一个全新安装的系统(Linux),其中尚未定义任何。我读过并使用过,我认为我很了解它,但我不知道当没有存在时会发生什么。 我不能附加到不存在的东西上,但我希望当前发现的所有重要库都能正常工作,因此要小心,我在Python中使用了来获取所有标准值。然后我为定义了一个-变量,包括我刚刚找到的所有节点,以及我的新目录。但是哇,很多东西都停止工作了!P
尝试,但它给我一个错误。与这里的许多其他问题类似,但提供的解决方案在我安装后无法解决错误。 我的文件 我正在使用Windows 7,蟒蛇3.4(我听说与安装MySQL-python不兼容,所以我下载了mysql客户端1.3.6)。 当我运行时,它会导致 同样,它在运行时要求配置win.h,以及一个可怕的错误 我对此很困惑。我一直在看的教程偏离了我这里,我不知道如何处理mysqlclient的WHL