如何修改R语言中S3方法的默认参数?
能否修改R语言中S3方法的默认参数?
当然可以修改,但和普通函数的修改逻辑略有不同——因为S3方法通常属于某个包的命名空间,直接修改会遇到权限或访问限制。咱们一步步拆解:
先回顾普通函数的参数修改
修改普通函数的默认参数确实很简单,用formals()就能轻松搞定,比如table()函数:
# 查看table的默认参数 args(table) #> function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = c("no", "ifany", "always"), dnn = list.names(...), deparse.level = 1) # 修改useNA的默认值为"always" formals(table)$useNA <- "always" # 验证修改后的参数 args(table) #> function (..., exclude = if (useNA == "no") c(NA, NaN), useNA = "always", dnn = list.names(...), deparse.level = 1)
S3方法修改时的问题
但碰到S3方法(比如utils包中的str.default)时,直接用同样的方法会报错:
# 查看str.default的list.len默认值 formals(utils:::str.default)$list.len #> [1] 99 # 尝试直接修改,触发错误 formals(utils:::str.default)$list.len <- 100 #> Error in formals(utils:::str.default)$list.len <- 100 : object 'utils' not found
这是因为str.default是utils包命名空间内的非导出函数,直接通过formals()修改会受到R的命名空间保护机制限制。
正确修改S3方法默认参数的方式
要修改这类包内S3方法的参数,需要用assignInNamespace()函数来操作命名空间内的函数:
方法一:重新定义函数并赋值回命名空间
# 先获取原函数的参数列表 old_formals <- formals(utils:::str.default) # 修改目标参数的默认值 old_formals$list.len <- 150 # 重新定义str.default函数,使用修改后的参数 new_str_default <- function(x, ..., list.len = old_formals$list.len, give.attr = TRUE, str = str, vec.len = strOptions()$vec.len, digits = strOptions()$digits, nchar.max = strOptions()$nchar.max) { utils:::str.default(x, ..., list.len = list.len, give.attr = give.attr, str = str, vec.len = vec.len, digits = digits, nchar.max = nchar.max) } # 将新函数赋值回utils包的命名空间 assignInNamespace("str.default", new_str_default, ns = "utils") # 验证修改结果 formals(utils:::str.default)$list.len #> [1] 150
方法二:直接修改参数后赋值
更简洁的写法可以直接修改参数列表,再生成新函数:
# 获取原函数的参数 f <- formals(utils:::str.default) # 修改目标参数 f$list.len <- 200 # 生成新函数的代码文本并解析执行 new_func <- eval(parse(text = sprintf( "function(%s) { utils:::str.default(%s) }", paste(names(f), "=", f, collapse = ", "), paste(names(f), collapse = ", ") ))) # 赋值回命名空间 assignInNamespace("str.default", new_func, ns = "utils") # 检查修改后的参数 formals(utils:::str.default)$list.len #> [1] 200
注意事项
- 修改包命名空间内的函数属于“hack”行为,可能会导致包功能异常,且在包更新后修改会失效;
- 如果只是个人使用,更推荐显式指定参数调用(比如
str(your_object, list.len = 150)),或者创建自己的S3方法来覆盖原方法,这样更安全可控。
内容的提问来源于stack exchange,提问作者Khaynes
相关产品推荐
相关产品推荐

