Vic*_*rti 35 python closures functional-programming
有没有办法修改闭包内的其中一个变量的绑定值?看一下这个例子来更好地理解它.
def foo():
var_a = 2
var_b = 3
def _closure(x):
return var_a + var_b + x
return _closure
localClosure = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
# ...but what magic? Is this even possible?
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 +1 == 4
Run Code Online (Sandbox Code Playgroud)
rec*_*ive 26
由于非局部的魔力,在python 3中很有可能.
def foo():
var_a = 2
var_b = 3
def _closure(x, magic = None):
nonlocal var_a
if magic is not None:
var_a = magic
return var_a + var_b + x
return _closure
localClosure = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
print(a)
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
localClosure(0, 0)
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 +1 == 4
print(b)
Run Code Online (Sandbox Code Playgroud)
Gre*_*ill 21
我不认为在Python中有任何方法可以做到这一点.定义闭包时,将捕获封闭范围中变量的当前状态,并且不再具有可直接引用的名称(从闭包外部).如果foo()再次调用,则新闭包将与封闭范围具有不同的变量集.
在您的简单示例中,您可能最好使用类:
class foo:
def __init__(self):
self.var_a = 2
self.var_b = 3
def __call__(self, x):
return self.var_a + self.var_b + x
localClosure = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
# ...but what magic? Is this even possible?
localClosure.var_a = 0
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 +1 == 4
Run Code Online (Sandbox Code Playgroud)
如果你使用这种技术,我将不再使用该名称,localClosure因为它不再是一个闭包.但是,它的工作原理与之相同.
Vic*_*rti 11
我找到了Greg的另一个答案答案,稍微不那么冗长,因为它使用Python 2.1的自定义函数属性(可以方便地从它们自己的函数内部访问).
def foo():
var_b = 3
def _closure(x):
return _closure.var_a + var_b + x
_closure.func_dict['var_a'] = 2
return _closure
localClosure = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
# ...but what magic? Is this even possible?
# apparently, it is
localClosure.var_a = 0
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 +1 == 4
Run Code Online (Sandbox Code Playgroud)
以为我会发布完整性.无论如何干杯.
我们做了以下事情.我认为这比其他解决方案简单.
class State:
pass
def foo():
st = State()
st.var_a = 2
st.var_b = 3
def _closure(x):
return st.var_a + st.var_b + x
def _set_a(a):
st.var_a = a
return _closure, _set_a
localClosure, localSetA = foo()
# Local closure is now "return 2 + 3 + x"
a = localClosure(1) # 2 + 3 + 1 == 6
# DO SOME MAGIC HERE TO TURN "var_a" of the closure into 0
localSetA(0)
# Local closure is now "return 0 + 3 + x"
b = localClosure(1) # 0 + 3 +1 == 4
print a, b
Run Code Online (Sandbox Code Playgroud)
我通过使用单项列表而不是普通变量来解决类似的限制。它很丑陋,但它有效,因为修改列表项不会被解释器视为绑定操作。
例如:
def my_function()
max_value = [0]
def callback (data)
if (data.val > max_value[0]):
max_value[0] = data.val
# more code here
# . . .
results = some_function (callback)
store_max (max_value[0])
Run Code Online (Sandbox Code Playgroud)