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

Posted

技术标签:

【中文标题】R中的全局变量和局部变量【英文标题】:Global and local variables in R 【发布时间】:2012-06-09 20:57:20 【问题描述】:

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

我在网上看到一些帖子说如果我使用=<- 我将在当前环境中分配变量,而使用<<- 我可以在函数内部访问全局变量。

但是,我记得在 C++ 中,每当您在括号 内声明一个变量时,就会出现局部变量,所以我想知道这对于 R 是否相同?还是只是为了R中的函数,我们才有了局部变量的概念。

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


   x=matrix(1:10,2,5)

print(x[2,2])
[1] 4

【问题讨论】:

除了这些答案之外还要运行一些代码:globalenv(); globalenv() %&gt;% parent.env; globalenv() %&gt;% parent.env %&gt;% parent.env, ... @isomorphismes, Error: could not find function "%&gt;%" 。这是另一种形式的任务吗? R-help 上的相关帖子:What does the "<<-" operator mean?. @AaronMcDaid 嗨,很抱歉没有尽快回复!那是来自require(magrittr)。这是一种在右侧 (x | f1 | f2 | f3) 而非左侧 (f3( f2( f1( x ) ) )) 应用函数的方式。 【参考方案1】:

在函数内部声明的变量是该函数的局部变量。例如:

foo <- function() 
    bar <- 1

foo()
bar

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

如果你想让bar 成为一个全局变量,你应该这样做:

foo <- function() 
    bar <<- 1

foo()
bar

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

但是,与 C、C++ 或许多其他语言不同,括号不能确定变量的范围。比如下面的代码sn-p:

if (x > 10) 
    y <- 0

else 
    y <- 1

yif-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

【讨论】:

【参考方案2】:

&lt;- 在当前环境下赋值。

当你在一个函数中时,R 会为你创建一个新环境。默认情况下,它包含创建它的环境中的所有内容,因此您也可以使用这些变量,但您创建的任何新内容都不会写入全局环境。

在大多数情况下,&lt;&lt;- 将分配给已经在全局环境中的变量,或者在全局环境中创建一个变量,即使您在函数内部也是如此。然而,它并不像那样简单。它的作用是检查父环境以查找具有感兴趣名称的变量。如果它在您的父环境中找不到它,它会转到父环境的父环境(在创建函数时)并在那里查找。它继续向上到全局环境,如果在全局环境中找不到它,它将在全局环境中分配变量。

这可能说明正在发生的事情。

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”的值是有意义的。下面是我们看到&lt;&lt;- 实际在做什么的地方。打印的下一个值是“in baz - <<- 之后。这是因为&lt;&lt;- 不查看当前环境(除非您在全局环境中,在这种情况下&lt;&lt;- 的行为类似于&lt;-)。所以在baz 内部,bar 的值保持为“in baz - before baz,foo 内部的 bar 副本就会更改为“in baz”,但我们可以看到全局 bar 没有改变。这是因为foo 内部定义的bar 的副本在我们创建baz 时位于父环境中,因此这是&lt;&lt;- 看到的bar 的第一个副本,因此它分配给它的副本.所以&lt;&lt;- 不只是直接分配给全局环境。

&lt;&lt;- 很棘手,如果可以避免的话,我不建议使用它。如果您真的想分配给全局环境,您可以使用 assign 函数并明确告诉它您要全局分配。

现在我将&lt;&lt;- 更改为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 内打印 bar,即使在调用baz 之后,值也是“in 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"

【讨论】:

我可以配置一个函数,让它里面的环境和外面一样吗?这意味着使用 是的,但这是一个糟糕的主意。我不会帮你,因为那太糟糕了。最好返回结果并让用户决定如何使用它们。【参考方案3】:

更多类似的内容

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”

【讨论】:

以上是关于R中的全局变量和局部变量的主要内容,如果未能解决你的问题,请参考以下文章

C语言中的“局部变量”是啥意思?

C语言中的全局变量和局部变量

C语言基础:作用域规则(局部变量,全局变量,形式参数)全局变量与局部变量在内存中的区别初始化局部变量和全局变量

C语言中的局部变量和全局变量

C语言中的局部变量和全局变量

如何判断函数中的变量是全局变量还是局部变量