R中的全局和局部variables

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

我在互联网上看到一些post说如果我使用=<-我将分配在当前环境中的variables,并与<<-我可以访问一个函数内的全局variables。

然而,正如我记得在C ++局部variables出现,每当你在括号{}内声明一个variables,所以我想知道这是否相同的R? 还是只是在R中的函数 ,我们有局部variables的概念。

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

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

在函数中声明的variables是该函数的局部variables。 例如:

 foo <- function() { bar <- 1 } foo() bar 

给出以下错误: Error: object 'bar' not found

如果你想使bar变成全局variables,你应该这样做:

 foo <- function() { bar <<- 1 } foo() bar 

在这种情况下, bar可以从函数外部访问。

但是,与C,C ++或许多其他语言不同,括号不能确定variables的范围。 例如,在以下代码片段中:

 if (x > 10) { y <- 0 } else { y <- 1 } 

yif-else语句之后仍然可以访问。

正如你所说,你也可以创build嵌套的环境。 你可以看看这两个链接,了解如何使用它们:

  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

这里有一个小例子:

 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为你创build一个新的环境。 默认情况下,它包含创build它的环境中的所有内容,以便您可以使用这些variables,但是创build的任何新内容都不会写入全局环境。

在大多数情况下, <<-将分配给已经在全局环境中的variables,或者在全局环境中创build一个variables,即使你在一个函数内。 但是,这不是那么简单。 它所做的是检查具有感兴趣的名称的variables的父级环境。 如果它没有在你的父环境中find它,它会转到父环境的父(在创build函数的时候)并且看起来在那里。 它继续向上的全球环境,如果没有在全球环境中find它将分配variables在全球环境。

这可能说明发生了什么事情。

 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 ,所以它应该仍然是全球性的 – 这是有道理的。 第二次,我们打电话给baz之前打印它在foo里面,所以“in foo”的值是有道理的。 以下是我们看到什么<<-实际上在做什么。 打印的下一个值是“in baz – before << – ”,即使打印语句在<<- 。 这是因为<<-不看当前的环境(除非你在全球环境中,在这种情况下<<-就像<- )。 所以baz的价值在巴兹 – “之前”保持不变。 一旦我们打电话给baz里面的酒吧的副本改为“巴斯”,但我们可以看到,全球bar是不变的。 这是因为当我们创buildbaz时,在foo定义的bar的副本在父环境中,所以这是<<-看到的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之后,它的值也是“in foo”。 这是因为assign从来没有考虑过foo里的bar的副本,因为我们已经知道在哪里看。 然而,这一次在全球环境中bar的价值已经被改变了,因为我们明确地在那里分配了。

现在你也问了关于创build局部variables的问题,你也可以很容易地做到这一点,而无需创build一个函数…我们只需要使用local函数。

 bar <- "global" # local will create a new environment for us to play in local({ bar <- "local" print(bar) }) #[1] "local" bar #[1] "global"