闭包中引用循环变量的问题
2016-12-25 20:21
351 查看
今天在看Go的语法,突然想对比一下python和Go的闭包机制的区别。
假如闭包调用循环变量,在Go中的实现方法为,循环中用一个新的变量保存这个循环变量的值,具体实现代码如下:
//Go
package main
import (
"fmt"
"reflect"
)
func main() {
var funcArray = count()
for index := range funcArray {
funcArray[index]()
}
}
func count() []func() {
var a = make([]func(), 3)
for index := range a {
indexCopy := index
a[index] = func() {
fmt.Println(indexCopy)
}
}
return a
}
三次循环中产生了三个新的indexCopy的量,于是这个程序最后打印出0, 1, 2.
但是在python中,必须这样实现:
#python
def count():
l = []
for i in range(3):
def f(i):
def g():
return i
return g
l.append(f(i))
return l
f1, f2, f3 = count()
print f1()
print f2()
print f3()
先构造一个函数f(i)把i的值固定住,加入list中,实现引用循环变量的功能。
这时候问题来了,为什么python不能像go一样,新建一个循环变量的拷贝,像下面这样呢:#python
def count():
l = []
for i in range(3):
v = i
def f(i):
return v
l.append(f(i))
return l这是python gc决定的。在for的三次循环中,变量v的地址是不变的,只是每次循环分别指向了常量区不同的常量。所以到了最后三个闭包函数所保存的v地址是一样的,而且都指向了常量区中的2,而Go中则是三个闭包函数保存着三个indexCopy变量的地址。
假如闭包调用循环变量,在Go中的实现方法为,循环中用一个新的变量保存这个循环变量的值,具体实现代码如下:
//Go
package main
import (
"fmt"
"reflect"
)
func main() {
var funcArray = count()
for index := range funcArray {
funcArray[index]()
}
}
func count() []func() {
var a = make([]func(), 3)
for index := range a {
indexCopy := index
a[index] = func() {
fmt.Println(indexCopy)
}
}
return a
}
三次循环中产生了三个新的indexCopy的量,于是这个程序最后打印出0, 1, 2.
但是在python中,必须这样实现:
#python
def count():
l = []
for i in range(3):
def f(i):
def g():
return i
return g
l.append(f(i))
return l
f1, f2, f3 = count()
print f1()
print f2()
print f3()
先构造一个函数f(i)把i的值固定住,加入list中,实现引用循环变量的功能。
这时候问题来了,为什么python不能像go一样,新建一个循环变量的拷贝,像下面这样呢:#python
def count():
l = []
for i in range(3):
v = i
def f(i):
return v
l.append(f(i))
return l这是python gc决定的。在for的三次循环中,变量v的地址是不变的,只是每次循环分别指向了常量区不同的常量。所以到了最后三个闭包函数所保存的v地址是一样的,而且都指向了常量区中的2,而Go中则是三个闭包函数保存着三个indexCopy变量的地址。
相关文章推荐
- JavaScript的闭包问题(闭包解决引用循环变量的问题)
- swift之闭包循环引用问题及解决方式
- Xcode8调试黑科技:Memory Graph实战解决闭包引用循环问题
- 管道下while循环中定义的变量在退出while循环时引用为空的问题
- 15.8 Swift闭包属性引起的循环强引用问题
- swift闭包中解决循环引用的问题
- 解决swift中闭包中循环引用self 的问题
- X-code -- xcode8之Memory Graph实战解决闭包引用循环问题
- 使用 let 解决for 循环闭包 i变量问题
- Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
- Block的引用循环问题 (ARC & non-ARC) 【 引用外部变量或对象 】
- Xcode8调试黑科技:Memory Graph实战解决闭包引用循环问题
- javascript中的闭包循环变量只能取最后一个值问题
- 15.9 Swift解决闭包引起的循环强引用问题
- Xcode8的调试技能Memory Graph 实战解决闭包引用循环问题
- 闭包的循环引用问题
- Swift自定义数据模型及闭包的循环引用问题
- Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
- js循环里进行回调,引用循环里的变量,发现只是最后值的问题
- 解决循环引用问题系列 - 成员变量访问问题