【问题标题】:overwrite variable in parent function from inner function without making variable outside parent function从内部函数覆盖父函数中的变量而不在父函数外部创建变量
【发布时间】:2018-10-04 12:51:21
【问题描述】:

我正在尝试用“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。

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以将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()
    

    但是要小心,因为使用诸如此类的副作用会使代码更加复杂,而且通常是不可取的。

    【讨论】:

    • 我可以使用assign覆盖矩阵中的特定元素吗?如 assign("visited[row,col]", 30, envir = parent.frame())?
    【解决方案2】:

    这里有 3 种选择。 (1) 不更改 inner_func 并且 (3) 不更改 outer_func

    1) 复制并重置inner_func 的环境outer_func 内复制inner_func 并将当前环境强制为副本。 inner_func 没有做任何更改,outer_func 只添加了一行,这既可以复制也可以更改其环境。

    outer_func <- function() {
      a <- 10
      environment(inner_func) <- environment() 
      inner_func()
      print(a)
    }
    
    outer_func()
    ## [1] 30
    

    2) 在outer_func 中嵌套inner_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
    

    【讨论】:

      【解决方案3】:

      其他答案集中在如何让 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 中定义。现在赋值 &lt;&lt;- 找到 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没有赋值,所以GlobalEnv中不存在a。它仅在 outer_func 中更改,这是唯一存在的地方。

      a
      #Error: object 'a' not found
      

      【讨论】:

        猜你喜欢
        • 2020-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-10
        • 1970-01-01
        • 1970-01-01
        • 2022-11-27
        相关资源
        最近更新 更多