Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中修改闭包的绑定变量_Python_Functional Programming_Closures - Fatal编程技术网

在Python中修改闭包的绑定变量

在Python中修改闭包的绑定变量,python,functional-programming,closures,Python,Functional Programming,Closures,有没有办法修改闭包中某个变量的绑定值?看看这个例子,更好地理解它 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

有没有办法修改闭包中某个变量的绑定值?看看这个例子,更好地理解它

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

为什么不使用函数foo的var_a和var_b参数呢

def foo(var_a = 2, var_b = 3):
    def _closure(x):
        return var_a + var_b + x
    return _closure

localClosure = foo() # uses default arguments 2, 3
print localClosure(1) # 2 + 3 + 1 = 6

localClosure = foo(0, 3)
print localClosure(1) # 0 + 3 + 1 = 4

我认为在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

如果您使用这种技术,我将不再使用名称
localClosure
,因为它实际上不再是一个闭包。但是,它的工作原理与一个相同。

我找到了Greg的另一个答案,稍微不那么详细,因为它使用Python2.1的自定义函数属性(可以从自己的函数内部方便地访问这些属性)


我想我会把它贴出来。无论如何,干杯。

这在python 3中是完全可能的,多亏了的魔力


我们已经做了以下工作。我认为它比这里的其他解决方案更简单

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

我通过使用一个项目列表而不是一个普通变量来解决类似的限制。这很难看,但它可以工作,因为解释器不会将修改列表项视为绑定操作

例如:

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])

与要求的略有不同,但您可以:

def f():
    a = 1
    b = 2
    def g(x, a=a, b=b):
        return a + b + x
    return g

h = f()
print(h(0))
print(h(0,2,3))
print(h(0))

并将闭包设置为默认值,以便在需要时覆盖

也许还有更进一步的方法(即使对我的提议来说似乎已经晚了几年:-)


在我看来,提出的课堂解决方案更容易阅读。但是,如果您试图修改装饰器中的自由变量,此解决方案可能会派上用场:与基于类的解决方案相比,使用functools.wrapps来保存装饰函数的元数据更容易。

这并不能完全解决我的问题,因为我需要修改已经创建的闭包的值。也就是说,您的答案要求我每次需要更改绑定变量时都创建一个新的闭包。+1:第一类对象,而不是闭包。闭包是一种特殊的非对象事物。对象比闭包更清晰、更容易处理。事实上有一种方法。非本地的。看我的帖子。我也会的,这肯定比另一种方式好。我的意思是,默认情况下,它应该是nonlocalDoh!我本想说我不会的。在我看来,它仍然很怪异。关于更改值的可选参数的整个位。整件事应该是一门课。但无论如何,我离题了。
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
def foo():
    var_a = 2
    var_b = 3

    def _closure(x):
            return var_a + var_b + x

    return _closure

def bar():
        var_a = [2]
        var_b = [3]

        def _closure(x):
                return var_a[0] + var_b[0] + x


        def _magic(y):
            var_a[0] = y

        return _closure, _magic

localClosureFoo = foo()
a = localClosureFoo(1)
print a



localClosureBar, localClosureBarMAGIC = bar()
b = localClosureBar(1)
print b
localClosureBarMAGIC(0)
b = localClosureBar(1)
print b
def f():
    a = 1
    b = 2
    def g(x, a=a, b=b):
        return a + b + x
    return g

h = f()
print(h(0))
print(h(0,2,3))
print(h(0))
def foo():
    def _closure(x):
        return _closure.var_a + _closure.var_b + x
    _closure.var_a = 2
    _closure.var_b = 3
    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
# ...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
print(b)