<-
在当前环境中进行赋值操作。
在函数内部时,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,所以它应该仍然是全局的——这很有道理。第二次打印是在调用baz之前在foo内部打印的,所以"in foo"的值是有意义的。接下来我们可以看到<<-实际上做了什么。下一个打印的值是"in baz - before <<-",即使print语句出现在<<-之后。这是因为<<-不会查找当前环境(除非您在全局环境中,在这种情况下<<-的作用类似于<-)。因此,在baz内部,bar的值保持为"in baz - before <<-"。一旦我们调用了baz,foo内部的bar副本就会被更改为"in baz",但正如我们所看到的,全局的bar没有改变。这是因为定义在foo内部的bar副本在创建baz时位于父环境中,因此这是<<-所看到的第一个bar副本,并因此分配给它的副本。因此,<<-不仅直接分配给全局环境。
<<-很棘手,如果可以避免,我不建议使用它。如果您真的想分配给全局环境,可以使用assign函数并明确告诉它您想要全局分配。
现在我将<<-更改为分配语句,我们可以看到其效果:
bar <- "global"
foo <- function(){
bar <- "in foo"
baz <- function(){
assign("bar", "in baz", envir = .GlobalEnv)
}
print(bar)
baz()
print(bar)
}
bar
foo()
bar
所以两次在 foo
内部打印bar
时,即使调用了baz
,其值仍为“in foo”。这是因为assign
从未考虑过foo
内部的bar
副本,因为我们告诉它确切的查找位置。但是,这一次全局环境中的bar
的值发生了变化,因为我们明确地进行了赋值。
现在你还问如何创建局部变量,你也可以很容易地做到,而无需创建函数...我们只需要使用local
函数。
bar <- "global"
local({
bar <- "local"
print(bar)
})
bar
globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env
,... - isomorphismes错误:找不到函数“%>%”
。那是另一种赋值形式吗? - Aaron McDaidrequire(magrittr)
。这是一种在右侧应用函数(x | f1 | f2 | f3
)而不是在左侧的方法(f3(f2(f1(x)))
)。 - isomorphismes