首页 文章

< - 和<< - [1]之间的区别

提问于
浏览
3

这个问题在这里已有答案:

情况 1:

rm(list = ls())
foo <- function(x = 6){
  set <- function(){
  x <- x*x}
  set()
x}
foo()
# [1] 6

案例 2:

rm(list = ls())
foo <- function(x = 6){
set <- function(){
  x <<- x*x}
  set()
  x}
foo()
# [1] 36

我读到<<-运算符可用于为与当前环境不同的环境中的对象赋值。它表示使用<<-的对象初始化可以对不在当前环境中的对象进行。我想问一下使用<<-可以初始化哪个环境的对象。在我的情况下环境是foo函数的环境,可以<<-初始化函数外部的对象或当前环境中的对象吗?完全混淆何时使用<-以及何时使用<<-

2 回答

  • 8

    运算符<<-是父作用域赋值运算符。它用于将最近的父作用域中的变量赋值给它所评估的作用域。因此,这些分配“粘在”函数调用之外的范围内。请考虑以下代码:

    fun1 <- function() {
        x <- 10
        print(x)
    }
    
    > x <- 5    # x is defined in the outer (global) scope
    > fun1()
    [1] 10      # x was assigned to 10 in fun1()
    > x
    [1] 5       # but the global value of x is unchanged
    

    在函数fun1()中,局部变量x被赋值为10,但在全局范围内,x的值不会更改。现在考虑重写函数以使用父作用域赋值运算符:

    fun2 <- function() {
        x <<- 10
        print(x)
    }
    
    > x <- 5
    > fun2()
    [1] 10      # x was assigned to 10 in fun2()
    > x
    [1] 10      # the global value of x changed to 10
    

    因为函数fun2()使用<<-运算符,所以在函数完成求值后,x“赋值”的赋值。 R 实际上做的是遍历fun2()之外的所有范围并查找包含名为x的变量的第一个范围。在这种情况下,fun2()之外的唯一范围是全局范围,因此它在那里进行赋值。

    正如一些人已经评论过的那样,<<-运算符被许多人所厌恶,因为它可以破坏 R 脚本的封装。如果我们将 R 函数视为一个独立的功能,则不应该允许它干扰调用它的代码的状态。滥用<<-赋值运算符会冒这样做的风险。

  • 2

    <<-运算符可用于将变量分配给全局环境。使用assign函数比使用<<-更好。您可能不需要使用<<- - 函数所需的输出应作为 R 中的对象返回。

    这是一个例子

    f <- function(x) {
        y <<- x * 2 # y outside the function
    }
    
    f(5) # y = 10
    

    这相当于

    f <- function(x) {
        x * 2
    }
    
    y <- f(5) # y = 10
    

    使用 assign 函数,

    f <- function(x) {
        assign('y', x*2 envir=.GlobalEnv)
    }
    
    f(5) # y = 10
    

相关问题