提问人:Vokram 提问时间:6/6/2012 更新时间:3/15/2018 访问量:188830
R 中的全局变量和局部变量
Global and local variables in R
问:
我是 R 的新手,我对 R 中局部和全局变量的使用感到非常困惑。
我在互联网上读到一些帖子,说如果我使用或将在当前环境中分配变量,并且我可以在函数内部访问全局变量。=
<-
<<-
但是,正如我记得在 C++ 中,每当您在括号内声明变量时,都会出现局部变量,所以我想知道 R 是否也是如此?或者只是对于 R 中的函数,我们有局部变量的概念。{}
我做了一个小实验,这似乎表明只有括号是不够的,我做错了什么吗?
{
x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
答:
在函数中声明的变量是该函数的局部变量。例如:
foo <- function() {
bar <- 1
}
foo()
bar
给出以下错误: 。Error: object 'bar' not found
如果要创建全局变量,则应执行以下操作:bar
foo <- function() {
bar <<- 1
}
foo()
bar
在这种情况下,可以从函数外部访问。bar
但是,与 C、C++ 或许多其他语言不同,括号不能确定变量的范围。例如,在以下代码片段中:
if (x > 10) {
y <- 0
}
else {
y <- 1
}
y
在声明之后仍然可访问。if-else
正如你所说,你也可以创建嵌套环境。您可以查看以下两个链接,了解如何使用它们:
- http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
- http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html
这里有一个小例子:
test.env <- new.env()
assign('var', 100, envir=test.env)
# or simply
test.env$var <- 100
get('var') # var cannot be found since it is not defined in this environment
get('var', envir=test.env) # now it can be found
<-
在当前环境中进行分配。
当你在函数中时,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"
我们第一次打印酒吧时,我们还没有调用,所以它应该仍然是全局的 - 这是有道理的。我们第二次打印它是在调用之前的内部,所以值“in foo”是有意义的。以下是我们看到实际在做什么的地方。打印的下一个值是“in baz - before <<-”,即使 print 语句位于 .这是因为在当前环境中不看(除非您在全局环境中,在这种情况下,就像 )。因此,在酒吧的值内保持为“在 baz - << 之前”。一旦我们调用 bar 的副本,里面的 bar 就会更改为“in baz”,但正如我们所看到的,全局是不变的。这是因为当我们创建时,在 中定义的副本位于父环境中,因此这是它看到的第一个副本,因此它分配给的副本。所以不仅仅是直接分配给全球环境。foo
foo
baz
<<-
<<-
<<-
<<-
<-
baz
baz
foo
bar
bar
foo
baz
bar
<<-
<<-
<<-
很棘手,如果可以避免,我不建议使用它。如果确实要分配给全局环境,可以使用 assign 函数并明确告诉它您要全局分配。
现在我将 更改为 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"
因此,即使在调用 之后,我们两次打印值内部的条形图都是“in foo”。这是因为从来没有考虑过 foo 内部的副本,因为我们告诉它确切地在哪里看。但是,这一次全局环境中的 bar 值发生了变化,因为我们在那里显式分配了 bar。foo
baz
assign
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"
评论
沿着同样的思路再多一点
attrs <- {}
attrs.a <- 1
f <- function(d) {
attrs.a <- d
}
f(20)
print(attrs.a)
将打印“1”
attrs <- {}
attrs.a <- 1
f <- function(d) {
attrs.a <<- d
}
f(20)
print(attrs.a)
将打印“20”
评论
globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env
Error: could not find function "%>%"
require(magrittr)
x | f1 | f2 | f3
f3( f2( f1( x ) ) )