【问题标题】:Global and local variables in RR中的全局变量和局部变量
【发布时间】: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() %>% parent.env; globalenv() %>% parent.env %>% parent.env, ...
  • @isomorphismes, Error: could not find function "%>%" 。这是另一种形式的任务吗?
  • R-help 上的相关帖子:What does the "<<-" operator mean?.
  • @AaronMcDaid 嗨,很抱歉没有尽快回复!那是来自require(magrittr)。这是一种在右侧 (x | f1 | f2 | f3) 而非左侧 (f3( f2( f1( x ) ) )) 应用函数的方式。

标签: r


【解决方案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 语句之后仍然可以访问。

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

  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

【讨论】:

    【解决方案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”

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 2019-04-04
      • 2013-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多