在下面的例子,为什么f$i
和f$get_i()
返回不同的结果?
factory <- function() {
my_list <- list()
my_list$i <- 1
my_list$increment <- function() {
my_list$i <<- my_list$i + 1
}
my_list$get_i <- function() {
my_list$i
}
my_list
}
f <- factory()
f$increment()
f$get_i() # returns 2
f$i # returns 1
Run Code Online (Sandbox Code Playgroud)
f <- factory()
Run Code Online (Sandbox Code Playgroud)
创建my_list
对象my_list$i = 1
并将其分配给f
.所以现在f$i = 1
.
f$increment()
Run Code Online (Sandbox Code Playgroud)
my_list$i
仅增量.它不会影响f
.
现在
f$get_i()
Run Code Online (Sandbox Code Playgroud)
返回(先前递增)my_list$i
while
f$i
Run Code Online (Sandbox Code Playgroud)
返回不受影响 f$i
它'因为您使用<<-
了对全局对象进行操作的运算符.如果您将代码更改为
my_list$increment <- function(inverse) {
my_list$i <- my_list$i + 1
}
Run Code Online (Sandbox Code Playgroud)
my_list
将仅在increment
函数内增加.所以现在你明白了
> f$get_i()
[1] 1
> f$i
[1] 1
Run Code Online (Sandbox Code Playgroud)
让我在你的代码中添加一行代码,这样我们就能看到increment
肠子了:
my_list$increment <- function(inverse) {
my_list$i <- my_list$i + 1
return(my_list$i)
}
Run Code Online (Sandbox Code Playgroud)
现在,你可以看到<-
里面只有工作increment
,而<<-
在它之外运行.
> f <- factory()
> f$increment()
[1] 2
> f$get_i()
[1] 1
> f$i
[1] 1
Run Code Online (Sandbox Code Playgroud)
您编码的方式与功能范式非常相似。R 更常被用作脚本语言。因此,除非您确切地知道自己在做什么,否则使用 <<- 或在函数中包含函数是不好的做法。
你可以找到解释这里的功能环境的篇章。
环境是执行代码的空间/框架。环境可以嵌套,就像函数一样。
创建函数时,您附加了一个外壳环境,可以通过environment
. 这是封闭环境。
该函数在另一个环境中执行,该执行环境采用全新启动原则。执行环境是封闭环境的子环境。
例如,在我的笔记本电脑上:
> environment()
<environment: R_GlobalEnv>
> environment(f$increment)
<environment: 0x0000000022365d58>
> environment(f$get_i)
<environment: 0x0000000022365d58>
Run Code Online (Sandbox Code Playgroud)
f 是位于全局环境中的对象。
该函数increment
附有封闭环境 0x0000000022365d58,即函数的执行环境factory
。
我引用哈德利的话:
当你在另一个函数内部创建一个函数时,子函数的封闭环境是父函数的执行环境,执行环境不再是短暂的。
执行函数 f 时,会创建包含其中的my_list
对象的封闭环境。
可以使用以下ls
命令进行评估:
> ls(envir = environment(f$increment))
[1] "my_list"
> ls(envir = environment(f$get_i))
[1] "my_list"
Run Code Online (Sandbox Code Playgroud)
该<<-
运营商正在寻找在父母的环境中使用的变量。在这种情况下,my_list
找到的对象是直接上层环境中的对象,即函数的封闭环境。
因此,当进行增量时,它仅在该环境中而不是在全局中进行。
您可以通过以下方式替换该increment
功能来查看它:
my_list$increment <- function() {
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i <<- my_list$i + 1
}
Run Code Online (Sandbox Code Playgroud)
它给了我:
> f$increment()
[1] "environment"
<environment: 0x0000000013c18538>
[1] "Parent environment"
<environment: 0x0000000022365d58>
Run Code Online (Sandbox Code Playgroud)
get
存储环境名称后,您可以使用来访问您的结果:
> my_main_env <- environment(f$increment)
> get("my_list", env = my_main_env)
$i
[1] 2
$increment
function ()
{
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i <<- my_list$i + 1
}
<environment: 0x0000000022365d58>
$get_i
function ()
{
print("environment")
print(environment())
print("Parent environment")
print(parent.env(environment()))
my_list$i
}
<environment: 0x0000000022365d58>
Run Code Online (Sandbox Code Playgroud)