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

Vok*_*ram 120 r

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

我在互联网上阅读了一些帖子,说如果我使用=或者<-我将在当前环境中分配变量,并且<<-我可以在函数内部访问全局变量.

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

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

{
   x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
Run Code Online (Sandbox Code Playgroud)

bet*_*ido 143

在函数内声明的变量是该函数的本地变量.例如:

foo <- function() {
    bar <- 1
}
foo()
bar
Run Code Online (Sandbox Code Playgroud)

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

如果你想创建bar一个全局变量,你应该这样做:

foo <- function() {
    bar <<- 1
}
foo()
bar
Run Code Online (Sandbox Code Playgroud)

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

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

if (x > 10) {
    y <- 0
}
else {
    y <- 1
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


Das*_*son 125

<- 在当前环境中进行分配.

当您在函数内部时,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"
Run Code Online (Sandbox Code Playgroud)

我们第一次打印吧我们还没有打电话foo,所以它应该仍然是全局的 - 这是有道理的.我们第二次foo在调用之前将其打印出来,baz因此"foo"中的值是有意义的.以下是我们看到<<-实际行动的地方.打印的下一个值是"in baz - before << - ",即使print语句出现在<<-.这是因为<<-没有查看当前环境(除非您处于全局环境中,在这种情况下<<-就像这样<-).所以在bazbar的值内部保持"在baz - 之前<< - ".一旦我们调用baz内部的bar副本foo变为"in baz",但我们可以看到全局bar不变.这是因为我们在创建时在父环境中bar定义了它的副本,因此这是它看到的第一个副本,因此它分配给它的副本.所以不只是直接分配到全球环境.foobazbar<<-<<-

<<-很棘手,如果你能避免它,我不建议使用它.如果您确实要分配给全局环境,可以使用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"
Run Code Online (Sandbox Code Playgroud)

因此,foo即使在调用之后,我们两次打印条形内部的值都是"in foo" baz.这是因为我们assign从未考虑过barfoo内部的副本,因为我们告诉它确切的位置.但是,这次全局环境中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"
Run Code Online (Sandbox Code Playgroud)


小智 5

同样的道理

attrs <- {}

attrs.a <- 1

f <- function(d) {
    attrs.a <- d
}

f(20)
print(attrs.a)
Run Code Online (Sandbox Code Playgroud)

将打印“1”

attrs <- {}

attrs.a <- 1

f <- function(d) {
   attrs.a <<- d
}

f(20)
print(attrs.a)
Run Code Online (Sandbox Code Playgroud)

将打印“20”