我是R的新手,我对R中局部变量和全局变量的使用感到困惑。
我在互联网上阅读了一些帖子,说明我是否使用=
或<-
我将在当前环境中分配变量,并使用<<-
我可以访问全局变量在一个函数内部。
但是,正如我记得在C ++中,每当你在括号{}
中声明一个变量时就会出现局部变量,所以我想知道这对于R是否相同?或者仅仅是R中的函数我们有局部变量的概念。
我做了一个小实验,这似乎表明只有括号不够,我有什么不对吗?
{
x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
答案 0 :(得分:137)
在函数内声明的变量是该函数的本地变量。例如:
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
。
正如您所说,您还可以创建嵌套环境。您可以查看这两个链接以了解如何使用它们:
这里有一个小例子:
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
答案 1 :(得分:120)
<-
在当前环境中进行分配。
当你在函数内部时,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"
我们第一次打印栏时我们还没有调用foo
,所以它应该仍然是全局的 - 这是有道理的。我们第二次在调用foo
之前将其打印在baz
内,因此“foo”中的值是有意义的。以下是我们看到<<-
实际正在做什么的地方。打印的下一个值是“in baz - before&lt;&lt; - ”,即使print语句在<<-
之后。这是因为<<-
不会查看当前环境(除非您处于全局环境中,<<-
的行为类似于<-
)。因此,在baz
内,bar的值保持为“在baz中 - 之前&lt;&lt; - ”。一旦我们致电baz
,foo
内的条形图副本就会变为“在baz中”,但我们可以看到全局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"
因此,即使在调用foo
之后,我们都会在baz
内打印条形码,其值为“foo”。这是因为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"
答案 2 :(得分:2)
沿着相同的路线再多一点
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”