从内部函数覆盖父函数中的变量,而不在父函数外部创建变量

时间:2018-10-04 12:51:21

标签: r

我试图用'inner_func'中的值覆盖'outer_func'中的变量a。我不希望它在函数'outer_func'之外生成变量。

inner_func <- function(){
  a <<- 30
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

输出为10,但应为30。

3 个答案:

答案 0 :(得分:2)

您可以将assignparent.frame()一起使用(parent.frame()是外部函数的环境,在这种情况下parent.frame(2)是全局环境):

inner_func <- function(){
  assign("a", 30, envir = parent.frame())
}

outer_func <- function(){
  a <- 10
  inner_func()
  print(a)
}

outer_func()

但是要小心,因为使用类似的副作用会使代码复杂得多,并且通常是不可取的。

答案 1 :(得分:1)

这里有3个替代方案。 (1)对inner_func不做任何更改,而(3)对outer_func不做任何更改。

1)复制并重置inner_func的环境inner_func中复制outer_func的副本,并将当前环境强制转换为副本。 inner_func不会进行任何更改,outer_func仅添加了一行,并且两者都可以复制并更改其环境。

outer_func <- function() {
  a <- 10
  environment(inner_func) <- environment() 
  inner_func()
  print(a)
}

outer_func()
## [1] 30

2)将inner_func嵌套在external_func 中,另一种方法是将inner_func嵌套在outer_func内。

outer_func <- function() {

  inner_func <- function() {
    a <<- 30
  }

  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

3)通过arg传递环境另一种方法是通过参数将a所在的环境传递给inner_func。通过将父框架设置为该参数的默认值,我们可以避免对outer_func进行任何更改。

inner_func <- function(envir = parent.frame()) {
  envir$a <- 30
}

outer_func <- function() {
  a <- 10
  inner_func()
  print(a)
}

outer_func()
## [1] 30

注意

如果a定义为outer_func,则可以扩展其中的任何一个以设置特定的矩阵元素。

a <- matrix(1:4, 2)

在(1)和(2)中修改inner_func以使用,例如:

a[1,1] <<- 30

和(3)中的示例在inner_func中使用:

envir$a[1,1] <- 30

答案 2 :(得分:1)

其他答案集中在如何使outer_funcinner_func表现得像您期望的那样。我将尝试说明为什么他们不这样做。

如果重新定义inner_func以打印其父级环境,您会发现它不是调用方的环境,而是全局环境。

inner_func <- function(){
  print(parent.env(environment()))
  a <<- 30
}

现在调用outer_func,发现它正在尝试在该环境中而不是在a的环境中查找变量outer_func

outer_func()
#<environment: R_GlobalEnv>
#[1] 10

当您打印a时,在调用outer_func之后,它具有预期的值。

a
#[1] 30

函数inner_func找不到a,因此在GlobalEnv中创建了它。

将以上内容与以下内容进行比较。 inner_funcouter_func中定义。现在,分配<<-找到a并更改其值。

outer_func2 <- function(){
  inner_func <- function(){
    print(parent.env(environment()))
    a <<- 30
  }

  a <- 10
  inner_func()
  print(a)
}

rm(a)
outer_func2()
#<environment: 0xdd06e18>
#[1] 30

但是由于outer_func2未分配其值,因此a中不存在GlobalEnv。仅在outer_func(它存在的唯一位置)中进行了更改。

a
#Error: object 'a' not found