如何理解R环境与globalenv()函数在发牌代码中的作用
核心原理:R的环境作用域规则
要搞懂envir = globalenv()的作用,首先得明确R函数运行的基础规则:
- 函数运行时会创建一个独立的临时运行环境,默认情况下,你在函数内部对变量做的赋值操作,只会在这个临时环境里生效,不会修改全局工作环境里的同名变量。
- 你在函数内部读取变量时,如果临时环境里找不到这个变量,R会自动向上层环境查找,直到全局环境,所以你在
deal函数里读取deck的时候,能拿到你提前在全局环境定义好的完整牌堆数据。
代码逐段拆解
你看到的优化后代码完整逻辑是这样的:
deal <- function(){ # 第一步:从上层环境(这里就是全局环境)读取完整deck,取第一行作为当前发出的牌 card <- deck[1,] # 第二步:更新全局环境里的deck,移除已经发出的第一行牌 assign("deck", deck[-1,], envir = globalenv()) # 第三步:返回发出的牌 return(card) }
其中assign("deck", deck[-1,], envir = globalenv())三个参数的作用分别是:
- 第一个参数
"deck":指定要修改的变量名,必须是字符串格式 - 第二个参数
deck[-1,]:要给变量赋的新值,也就是去掉了第一行的剩余牌堆 - 第三个参数
envir = globalenv():明确指定赋值操作的生效环境是全局工作环境,而不是函数自己的临时环境。
实际运行流程演示
假设你提前在全局环境定义好了完整的52张牌堆:
# 初始化全局牌堆 deck <- data.frame( face = rep(c("A",2:10,"J","Q","K"),4), suit = rep(c("黑桃","红桃","方块","梅花"), each=13), value = rep(c(11,2:10,10,10,10),4) )
调用函数的过程是:
- 第一次调用
deal():函数读取全局的52张deck,取第一行返回,同时把全局deck改成剩下的51张 - 第二次调用
deal():读取的已经是51张的全局deck,取第一行返回,再把全局deck改成50张 - 以此类推,直到全局deck被取空
额外说明
这种直接修改全局变量的写法属于有副作用的操作,实际工程开发中不推荐使用,容易出现变量被意外修改的问题,但作为入门案例用来理解R的环境作用域逻辑非常直观。
内容的提问来源于stack exchange,提问作者Marina Bonatti
相关产品推荐
相关产品推荐

