gpt4 book ai didi

r - R中不同的封闭环境、函数环境等

转载 作者:行者123 更新时间:2023-12-04 09:21:31 25 4
gpt4 key购买 nike

我有几个关于函数的不同环境的问题。以下面的例子为例:

environment(sd)
# <environment: namespace:stats>

namespace:stats 是否指向函数 sd 的封闭环境?
pryr::where(sd) 
# <environment: package:stats>

package:stats 是否指向函数 sd 的绑定(bind)环境?

根据 Advanced R by Hadley Wickham :“封闭环境属于函数,永不改变……”

但是可以像下面这样更改函数的封闭环境:
new.env <- new.env()
environment(f) <- new.env

函数的环境属性表示函数的执行环境,对吗? An online article regarding R finding stuff through environments

总结一下我的问题:
  • 我们真的可以改变一个函数的封闭环境吗?
  • stats的那两个不同的环境是什么?包裹?
  • 函数的环境是什么?

  • 它类似于以前的帖子 in here .

    最佳答案

    域名注册地址:

  • 事实上,你可以改变封闭环境。 Hadley 可能在谈论打包函数。
  • 封闭和绑定(bind)环境。你是对的。
  • 那就是执行环境。它仅在函数运行时存在。


  • 函数环境

    在谈论功能时,您必须区分 4 种不同的环境:
  • 绑定(bind)环境是找到函数的环境(即它的名称存在的地方)。这是对象与其名称的实际绑定(bind)完成的地方。 find()为您提供绑定(bind)环境。
  • 封闭环境是最初创建函数的环境。这不一定与绑定(bind)环境相同(请参见下面的示例)。 environment()给你封闭的环境。
  • 本地环境是函数内的环境。你称之为执行环境。
  • 父框架或调用环境是调用函数的环境。

  • 为什么这很重要

    每个环境都有特定的功能:
  • 绑定(bind)环境是您找到函数的环境。
  • 本地环境是 R 寻找对象的第一个环境。
  • 一般规则是:如果 R 在本地环境中找不到对象,则它会在封闭环境中查找,依此类推。最后一个封闭环境总是 emptyenv() .
  • 父框架是 R 查找传递的对象的值的地方
    论据。

  • 您可以更改封闭环境

    实际上,您可以更改封闭环境。它是您无法更改的包中函数的封闭环境。在这种情况下,您不更改封闭环境,实际上是在新环境中创建了一个副本:
    > ls()
    character(0)
    > environment(sd)
    <environment: namespace:stats>
    > environment(sd) <- globalenv()
    > environment(sd)
    <environment: R_GlobalEnv>
    > ls()
    [1] "sd"
    > find("sd")
    [1] ".GlobalEnv" "package:stats" # two functions sd now
    > rm(sd)
    > environment(sd)
    <environment: namespace:stats>

    在这种情况下,第二个 sd有全局环境作为包围和绑定(bind)环境,但是原来的 sd仍然在包环境中找到,它的封闭环境仍然是那个包的命名空间

    当您执行以下操作时,可能会出现混淆:
    > f <- sd
    > environment(f)
    <environment: namespace:stats>
    > find("f")
    [1] ".GlobalEnv"

    这里会发生什么?封闭环境仍然是命名空间“stats”。这就是创建函数的地方。但是,绑定(bind)环境现在是全局环境。这就是名称“f”绑定(bind)到对象的地方。

    我们可以将封闭环境更改为新环境 e .如果你现在检查,封闭环境变成 e ,但是 e本身是空的。 f仍受全局环境约束。
    > e <- new.env()
    > e
    <environment: 0x000000001852e0a8>
    > environment(f) <- e
    > find("f")
    [1] ".GlobalEnv"
    > environment(f)
    <environment: 0x000000001852e0a8>
    > ls(e)
    character(0)
    e的封闭环境是全局环境。所以 f仍然像它的 shell 是全局环境一样工作。环境 e包含在其中,因此如果在 e 中找不到某些内容,函数在全局环境中查找等等。

    但是因为 e是一个环境,R 称之为父环境。
    > parent.env(e)
    <environment: R_GlobalEnv>
    > f(1:3)
    [1] 1

    命名空间和包环境

    这个原则也是“技巧”包使用的:
  • 该函数是在命名空间中创建的。这是一个被其他导入包的命名空间包围的环境,最终是全局环境。
  • 函数的绑定(bind)是在包环境中创建的。这是一个包含全局环境和可能的其他包的环境。

  • 原因很简单:对象只能在您所在的环境中或在其封闭环境中找到。
  • 一个函数必须能够找到其他函数(对象),因此局部环境必须可能被它导入的其他包的命名空间、基本包和最后的全局环境包围。
  • 一个函数必须可以从全局环境中找到。因此绑定(bind)(即函数的名称)必须位于由全局环境包围的环境中。这是包环境(不是命名空间!)

  • 一个例证:

    enter image description here

    现在假设您创建了一个以空环境为父级的环境。如果您将其用作函数的封闭环境,则不再有效。因为现在你绕过了所有的包环境,所以你再也找不到单一的函数了。
    > orphan <- new.env(parent = emptyenv())
    > environment(f) <- orphan
    > f(1:3)
    Error in sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), :
    could not find function "sqrt"

    父框架

    这就是它变得有趣的地方。父框架或调用环境是查找作为参数传递的值的环境。但是该父框架可以是另一个函数的本地环境。在这种情况下,R 首先查看其他函数的本地环境,然后查看调用函数的封闭环境,一直到全局环境,附加包的环境,直到到达空环境。这就是“找不到对象”错误所在的地方。

    关于r - R中不同的封闭环境、函数环境等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44427752/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com