R语言S3类print方法结合+运算符未按预期工作的原因探究
S3类与
+运算的打印异常原因分析 问题重现
定义带有自定义print方法的S3类后,执行数值相加操作时出现不符合预期的打印结果:
异常代码示例
abc <- function(x, ...) { UseMethod("abc") } abc.default <- function(x, ...) { structure(as.numeric(x), class="abc", hello=exp(1)) } print.abc <- function(x, type=c("hello", "numeric"), ...) { type <- match.arg(type) if (type=="numeric") { ret <- as.numeric(x); print(ret) } if (type=="hello") { ret <- attr(x, "hello"); print(ret) } } x <- abc(pi) y <- x+1 y # 预期输出pi+1,实际输出exp(1)
修复后代码示例
仅修改print.abc的type参数默认顺序,即可得到预期结果:
print.abc <- function(x, type=c("numeric", "hello"), ...) { type <- match.arg(type) if (type=="numeric") { ret <- as.numeric(x); print(ret) } if (type=="hello") { ret <- attr(x, "hello"); print(ret) } } y <- x+1 y # 输出预期的pi+1
原因解析
核心并非+运算符的行为异常,而是自定义print方法的默认参数逻辑导致的:
- 执行
x+1时,由于未为abc类定义自定义+.abc方法,R会调用默认的+.default:先将x转换为数值类型计算得到pi+1,再保留原对象的abc类属性和hello附加属性。换句话说,y的实际数值确实是pi+1,只是类仍为abc。 - 异常版本的
print.abc中,type参数的默认列表第一个元素是"hello",match.arg(type)会将其作为默认值。直接打印y时,会执行type="hello"分支,输出attr(y, "hello")即exp(1)。 - 修改
type参数列表顺序后,match.arg(type)的默认值变为"numeric",打印时会执行数值分支,输出y的实际数值pi+1,符合预期。
内容的提问来源于stack exchange,提问作者sigbert
相关产品推荐
相关产品推荐

