fea*_*ool 15 ruby python closures
我正在从一个项目的Ruby切换到Python.我很欣赏Python具有一流的功能和闭包,所以这个问题应该很简单.我只是没有弄清楚Python的惯用语是什么:
在Ruby中,我可以写:
def with_quietude(level, &block)
begin
saved_gval = gval
gval = level
yield
ensure
gval = saved_gval
end
end
Run Code Online (Sandbox Code Playgroud)
并称之为:
with_quietude(3) {
razz_the_jazz
begin_the_beguine
}
Run Code Online (Sandbox Code Playgroud)
(注意:我不是在询问Python try/finally处理,也不是关于保存和恢复变量的问题 - 我只想要一个在一些其他代码中包装块的非常重要的例子.)
或者,因为当我真正询问闭包时,有些答案会挂在上一个例子中的全局作业中,如果调用如下,该怎么办?(注意,这不会改变with_quietude的定义):
def frumble(x)
with_quietude {
razz_the_jazz(x)
begin_the_beguine(2 * x)
}
end
Run Code Online (Sandbox Code Playgroud)
你会如何在Python中实现类似的东西(而不是被Python专家嘲笑)?
mgi*_*son 10
再看看ruby的收益率,看起来你想要的东西如下contextlib.contextmanager:
from contextlib import contextmanager
def razz_the_jazz():
print gval
@contextmanager
def quietude(level):
global gval
saved_gval = gval
gval = level
try:
yield
finally:
gval = saved_gval
gval = 1
with quietude(3):
razz_the_jazz()
razz_the_jazz()
Run Code Online (Sandbox Code Playgroud)
此脚本输出:
3
1
Run Code Online (Sandbox Code Playgroud)
表明我们的上下文管理器确实gval在全局命名空间中重置.当然,我不会使用这个上下文管理器,因为它只能在全局命名空间中工作.(例如,它不适用于函数中的本地人).
这基本上是对赋值如何创建对象的新引用的限制,并且您永远不能通过直接赋值来改变对象.(改变对象的唯一方法是分配给它的一个属性或通过__setitem__(a[x] = whatever))