R中的全局变量和局部变量

时间:2012-06-05 20:04:19

标签: r

我是R的新手,我对R中局部变量和全局变量的使用感到困惑。

我在互联网上阅读了一些帖子,说明我是否使用=<-我将在当前环境中分配变量,并使用<<-我可以访问全局变量在一个函数内部。

但是,正如我记得在C ++中,每当你在括号{}中声明一个变量时就会出现局部变量,所以我想知道这对于R是否相同?或者仅仅是R中的函数我们有局部变量的概念。

我做了一个小实验,这似乎表明只有括号不够,我有什么不对吗?

{
   x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4

3 个答案:

答案 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

正如您所说,您还可以创建嵌套环境。您可以查看这两个链接以了解如何使用它们:

  1. http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
  2. http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html
  3. 这里有一个小例子:

    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; - ”。一旦我们致电bazfoo内的条形图副本就会变为“在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”