全局变量和范围-R



我不明白为什么R中的全局范围列表不能在函数内修改,如下所示:

global <<- list()
f <- function(x) {
global[[x]] <- "blah"
}
f(1)
f(2)
print(global)

输出为

list()

然而,我期待着输出:

[[1]]
[1] "blah"
[[2]]
[1] "blah"

为什么会这样?我是否也必须声明列表中的每个元素都是全局的?

对于在函数块之外声明的局部作用域变量,似乎也是如此。

谢谢!

我相信您只是对<<-的实际功能有点困惑。来自help("<<-"):

运算符<lt;-和->>通常仅用于函数中,以及导致在父环境中搜索现有被赋值变量的定义。如果找到这样的变量(并且其绑定未锁定),则重新定义其值,否则作业发生在全球环境中。

因此应该清楚的是,<<-不会在任何运行位置创建"全局变量"。事实上,R根本不是这样工作的。

相反,<<-执行一种"全局赋值",允许您修改当前范围之外的变量。

它是更精确的assign()的一种粗糙版本。通常不鼓励使用这两种工具,因为它们往往会打破R使用的函数式编程范式(即没有副作用)。和其他任何东西一样,它们也有自己的用途,但通常不用于常规变量处理。

基本上,由于您使用的是"<-"赋值,因此函数正在创建"全局"变量的副本,以便在函数的范围内使用。

这可以通过添加第二个函数g()来实现,该函数在"global"在f()中打印出来之前会更改其值,但这次使用的是"<<-"赋值。f()中的第一行为f(x)创建"global"的本地范围副本,然后使用g(x)更新"global)"的全局副本。

global <<- list()
f <- function(x) {
global[[x]] <- "blah"
g(x)
global
}
g <- function(x){
global[[x]] <<- "newblah"
}

f(1)  #prints 'blah', despite the fact the g(x) has already updated the value
global  #prints 'newblah'

如果f(x)仍然引用"global"的全局副本,它将打印在g(x)中分配的"newblah"。相反,它打印在f(x)中分配给"global"的本地范围副本的值。

然而,在任何函数外打印"global"表明,g(x)实际上更新了"global"的全局副本的值。

现在,如果你把g(x)移到f(x)里面,那么f(x)现在就是g(x)的父对象。在这种情况下,"<<-"指定在f(x)范围内的"global"的值。因此,"global"的全局副本仍然为空,但如果在f()的作用域中打印出"global)",则会得到更新的值。

global <<- list()
f <- function(x) {
global[[x]] <- "blah"
g <- function(x){
global[[x]] <<- "newblah"
}
g(x)
global
}

f(1) #prints 'newblah'
global #empty

相关内容

  • 没有找到相关文章