探究get()函数带/不带引号的参数求值差异及assign()与get()的使用陷阱
理解R中
assign()和get()的陷阱,尤其是get()的求值差异 咱们先从你给出的示例入手,一步步拆解问题:
首先看你的代码,你通过循环用assign()把names.foo里的每个小写字母作为变量名,赋值成对应的大写字母描述字符串——比如变量a的值是"This is: A",变量b是"This is: B",以此类推。
为什么get('names.foo')能返回原始向量?
当你调用get('names.foo')时,你给get()传的是带引号的字符串,它的逻辑非常直接:去当前环境里找一个叫names.foo的对象,然后返回它的值。这和你直接在控制台输入names.foo的效果是一样的,所以自然能拿到最初定义的letters向量。
重点:get()带引号 vs 不带引号的求值差异
这正是很多人容易踩坑的地方,两种写法的行为完全不同:
- 带引号的字符串参数(比如
get('names.foo')):参数本身就是目标对象的名称,get()直接按这个名称查找对象,返回它的值。 - 不带引号的符号/变量参数(比如
get(names.foo)):R会先对names.foo求值,得到它的内容——也就是你定义的c("a","b","c",...)这个向量。然后get()会尝试把这个向量的每个元素当作对象名去查找,但get()默认只接受单个字符,所以直接这么写会报错:
但如果取向量里的单个元素,比如get(names.foo) # 报错:Error in get(names.foo) : first argument has length > 1get(names.foo[1]),其实等价于get("a"),这时候就会返回你之前用assign()创建的变量a的值:"This is: A"。
这类场景里常见的陷阱
- 混淆“变量名的字符串”和“变量的值”:
assign()的第一个参数必须是字符串形式的变量名,而get()的参数如果是符号,会先求值再查找——很多人在循环里容易把这两者搞混,导致找不到对象或者赋值错误。 - 环境问题:默认情况下
assign()和get()都是在当前环境(比如全局环境)操作,但如果在函数内部使用,不小心就会把变量赋值到函数的局部环境,或者找不到全局环境里的对象。如果需要指定环境,可以用这两个函数的envir参数。
补充代码示例对比
# 你的原始代码 names.foo <- letters values.foo <- LETTERS for (i in 1:length(names.foo)){ assign(names.foo[i], paste("This is: ", values.foo[i])) } # 情况1:带引号,直接查找名为names.foo的对象 get('names.foo') # 输出:[1] "a" "b" "c" "d" "e" "f" "g" ... # 情况2:不带引号,先求值names.foo,再尝试查找每个元素(报错) get(names.foo) # Error in get(names.foo) : first argument has length > 1 # 情况3:不带引号但取单个元素,等价于get("a") get(names.foo[1]) # 输出:[1] "This is: A"
内容的提问来源于stack exchange,提问作者mmcarthy
相关产品推荐
相关产品推荐

