<-在当前环境中进行赋值。
当你在一个函数中时,R 会为你创建一个新环境。默认情况下,它包括创建它的环境中的所有内容,因此您也可以使用这些变量,但您创建的任何新内容都不会写入全局环境。
在大多数情况下<<-,即使您在函数内部,也会分配给全局环境中已经存在的变量或在全局环境中创建变量。然而,它并不像那样简单。它的作用是检查父环境以查找具有感兴趣名称的变量。如果它在您的父环境中找不到它,它会转到父环境的父环境(在创建函数时)并在那里查找。它继续向上到全局环境,如果在全局环境中找不到它,它将在全局环境中分配变量。
这可能说明正在发生的事情。
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
bar <- "in baz - before <<-"
bar <<- "in baz - after <<-"
print(bar)
}
print(bar)
baz()
print(bar)
}
> bar
[1] "global"
> foo()
[1] "in foo"
[1] "in baz - before <<-"
[1] "in baz - after <<-"
> bar
[1] "global"
我们第一次打印 bar 我们还没有调用foo所以它应该仍然是全局的——这是有道理的。我们第二次打印它是foo在调用之前的内部,baz所以“in foo”的值是有意义的。下面是我们看到<<-实际在做什么的地方。打印的下一个值是“in baz - before <<-”,即使 print 语句出现在<<-. 这是因为<<-不查看当前环境(除非您在全局环境中,这种情况下的<<-行为类似于<-)。所以bazbar 的值内部保持为“in baz - before <<-”。一旦我们调用bazbar inside of 的副本,foo就会更改为“in baz”,但我们可以看到全局bar没有变化。barfoo当我们创建时,它在父环境中定义,baz所以这是bar它<<-看到的第一个副本,因此是它分配给的副本。所以<<-不仅仅是直接分配给全局环境。
<<-很棘手,如果可以避免,我不建议使用它。如果您真的想分配给全局环境,您可以使用 assign 函数并明确告诉它您要全局分配。
现在我将其更改<<-为分配语句,我们可以看到它有什么效果:
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
assign("bar", "in baz", envir = .GlobalEnv)
}
print(bar)
baz()
print(bar)
}
bar
#[1] "global"
foo()
#[1] "in foo"
#[1] "in foo"
bar
#[1] "in baz"
因此,foo即使在调用baz. 这是因为我们assign从来没有考虑过 foo 内部的副本,bar因为我们告诉了它在哪里看。但是,这一次全局环境中 bar 的值发生了变化,因为我们在那里显式分配。
现在您还询问了有关创建局部变量的问题,您也可以很容易地做到这一点,而无需创建函数……我们只需要使用该local函数。
bar <- "global"
# local will create a new environment for us to play in
local({
bar <- "local"
print(bar)
})
#[1] "local"
bar
#[1] "global"