当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在Python中修改闭包的绑定变量》经验,为你挑选了4个好方法。

有没有办法修改闭包内的其中一个变量的绑定值?看一下这个例子来更好地理解它.

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

recursive.. 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)

卫生署!我想说我不会.它对我来说仍然看起来很奇怪和黑客.关于可选参数改变值的全部内容.整件事应该是一堂课.但无论如何,我离题了. (4认同)


Greg Hewgill.. 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

如果你使用这种技术,我将不再使用该名称,localClosure因为它不再是一个闭包.但是,它的工作原理与之相同.



1> recursive..:

由于非局部的魔力,在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)


卫生署!我想说我不会.它对我来说仍然看起来很奇怪和黑客.关于可选参数改变值的全部内容.整件事应该是一堂课.但无论如何,我离题了.

2> Greg Hewgill..:

我不认为在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因为它不再是一个闭包.但是,它的工作原理与之相同.



3> Vicent Marti..:

我找到了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

以为我会发布完整性.无论如何干杯.



4> Tim James..:

我们做了以下事情.我认为这比其他解决方案简单.

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

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有