在调试一个递归函数的时候,发现的一个变量作用域的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | a = 0 test <- function(){ a <- a+1 #assign("a", a+1, env=.GlobalEnv) if(a>3) print("reach") else{ print(a) test() } print(a) } test() |
该代码的原意是利用全局变量作一个递归,但实际上它会陷入死循环,永远都在打印1。关键在第4行,首先根据R的变量搜索路径,局部变量a取得全局变量a的值0,然而a<-a+1这一步,却是把值赋给局部变量a,而非全局变量a。所以每次调用test()函数a的值都会被置为0。如果想赋给全局变量,则应用第5行被注释的代码替换第4行的代码,才能得到如下正确的输出。
补充:a <<- a+1这种方式可以给全局变量赋值。
[1] 1 [1] 2 [1] 3 [1] "reach" [1] 4 [1] 4 [1] 4 [1] 4
当然如下纯粹用局部变量实现递归也是可以的,只是因为我的应用中需要用到一些全局变量,所以才面临了些诡异的问题。
1 2 3 4 5 6 7 8 9 10 11 12 | test <- function(a){ a <- a+1 if(a>3) print("reach") else{ print(a) test(a) } print(a) } test(0) |
python也是不需要使用global就可以取得全局变量的值,但是有赋值时就必须使用global,不然也是会变成局部变量。
不过python好的一点是,在一个作用域内,一个变量是局部还是全局是固定的,不会像R一样取全局变量存局部变量。
啊,是我搞错了,马上更正之:-)
我也是因为python的一致性认识,所以在R里就被这个给绕了