Python 闭包不支持修改 upvalue,有什么替代的解决方案?

2016-01-19 09:20:31 +08:00
 tabris17

如下代码:

def test_closure():
    x = 1
    def closure():
        x = 2
    closure()
    print x
test_closure()

x 仍然是 1

6340 次点击
所在节点    Python
67 条回复
est
2016-01-19 09:22:21 +08:00
暴力遍历 call frame 修改局部变量。动态语言你值得拥有。
tabris17
2016-01-19 09:28:03 +08:00
@est ……难道没有优雅一些的方法么?

不能修改 upvalue 岂不是连 PHP 都不如了? Python 当自强啊
est
2016-01-19 09:31:19 +08:00
>>> a=123
>>> def c():
... sys._getframe().f_back.f_locals['a'] = 456
...
...
>>> a
123
>>> c
<function c at 0x7f69c98df050>
>>> c()
>>> a
456
est
2016-01-19 09:32:39 +08:00
如此定义个函数:

upvalue = sys._getframe().f_back.f_locals

你想怎么改就怎么改。改别的进程里的 php 变量都可以做到。
clino
2016-01-19 09:34:55 +08:00
在 3 有新增关键字搞定这种情况

用 2 我面对楼主这种情况,一般用的是这样的方式

def test_closure():
----class v:pass
----v.x = 1
----def closure():
--------v.x = 2
----closure()
----print v.x
test_closure()
zhuangzhuang1988
2016-01-19 09:36:35 +08:00
def test_closure():
x = [1]
def closure():
x[0] = 2
closure()
print x[0]
test_closure()
arcas
2016-01-19 09:38:01 +08:00
python 3 nonlocal 关键字
clino
2016-01-19 09:38:34 +08:00
另外不是"闭包不支持修改 upvalue"
而是在
def closure():
----x = 2
这里的赋值有声明的作用,所以 python 认为这里声明了一个新的局部变量
arcas
2016-01-19 09:40:04 +08:00
def func1():
func1.x = 100
def func2():
func1.x = 200
func2()
print func1.x
tabris17
2016-01-19 09:53:01 +08:00
@clino 你这是语法上的解释,本质就是 python 不支持修改 upvalue
tabris17
2016-01-19 10:04:49 +08:00
@est 你这个办法,万一上层调用已经返回了咋办?
tabris17
2016-01-19 10:05:21 +08:00
@arcas 看来要换 3
vanxining
2016-01-19 10:05:51 +08:00
学习了。另外, upvalue 是 Lua 的说法?
tabris17
2016-01-19 10:08:50 +08:00
@vanxining 不是,闭包所引用的函数外部变量就称作 upvalue
kkwezard
2016-01-19 10:18:00 +08:00
@tabris17 我怎么只在 lua 里看到过 upvalue 这种说法。
xuboying
2016-01-19 10:22:00 +08:00
我也遇到了一样的问题

这里有个 remedy

https://segmentfault.com/q/1010000004211385
tabris17
2016-01-19 10:22:04 +08:00
@kkwezard lua 的叫法比较学术呗
clino
2016-01-19 10:26:37 +08:00
@tabris17 可是我给的代码就不是在修改 upvalue 了吗
tabris17
2016-01-19 10:27:13 +08:00
@vanxining
@kkwezard

除了 lua ,其他语言说到闭包只是强调了变量的作用域。但是实际上是有个专门术语来称呼这个 inherit variables from the parent scope 的,就是 upvalue 。

以下摘自 wiki 的闭包词条:

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。运行时,一旦外部的 函数被执行,一个闭包就形成了,闭包中包含了内部函数的代码,以及所需外部函数中的变量的引用。其中所引用的变量称作上值(upvalue)。
tabris17
2016-01-19 10:28:53 +08:00
@clino 你给的代码是修改 upvalue 引用的对象而已,不是修改了 upvalue 。 upvalue 本身是不可变的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/251731

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX