【问题标题】:How do I know which method will be called?我怎么知道会调用哪个方法?
【发布时间】:2017-11-23 12:58:37
【问题描述】:

如果我输入methods(print),我会得到一长串方法。

对于data.frame 类的对象,将调用print.data.frame

但这并不总是那么简单:

hw <- "hello world"
class(hw) # [1] "character"

没有print.character 方法。执行print(hw)时如何知道调用了哪个方法?

【问题讨论】:

  • 如果没有定义,它将使用默认方法
  • print.default 存在,但[.default 不存在,我怎么知道c("hello","world")[2] 调用了哪个方法?
  • 顺便说一句,你是在看到strict 包后开始检查这个的吗?
  • 不,我只是有时想成为源代码中的内容:),并确保我了解在构建自己的方法时发生了什么。

标签: r methods


【解决方案1】:

打开调试以进行打印,然后运行您的示例:

> debug(print)
> print("hello")
debugging in: print("hello")
debug: UseMethod("print")
Browse[2]>  <---------------------------- press Enter to step forward
debugging in: print.default("hello")  <-- this is the method that gets called
debug: {
    noOpt <- missing(digits) && missing(quote) && missing(na.print) && 
        missing(print.gap) && missing(right) && missing(max) && 
        missing(useSource) && missing(...)
    .Internal(print.default(x, digits, quote, na.print, print.gap, 
        right, max, useSource, noOpt))
}

【讨论】:

  • 它在这种情况下确实有效,谢谢,最后调用undebug(print) 否则你会永远卡住(作为旁注debugonce 不起作用,因为它需要调试两次)。如果我尝试它也不起作用:debug('[');c("hello","world")[2].
【解决方案2】:

你读过 Hadley 的 Advanced R 和关于对象的章节吗?它可能无法为您提供完整的答案,但从根本上讲,您所体验的是 C 中的方法调度与常规 S3 行为之间的区别。

[ 不是真正的 R 函数,它是 C 函数,使用什么方法的决定是在 C 中完成的。这并不意味着您不能为 [ 创建 S3 方法(或sum+[&lt;- 和其他 .Primitive 函数),但是当你这样做时,它更像是在为 C 函数制作一个包装器/预处理器,R 将在最终决定由基于与常规(和可扩展)R 类分开定义的类的 C 函数。

至少我是这么理解的。

【讨论】:

  • 非常感谢。因此,为了连接这些点(如果我错了,请任何人纠正我),用 C 编写的 S3 泛型不要调用 UseMethod,我仍然可以在它们上使用 methods 并尝试猜测,但如果我可以的话'找不到这种方式,我必须深入研究 C 代码并查找 DispatchGroupDispatchOrEval 调用。我可以通过在它们上调用pryr:ftype 来识别它们,它会将它们描述为原语。不过,这些都是例外,而不是人们通常首先想要调查的功能。
  • 对于其他情况,只要my_function是S3泛型,如果my_function.my_class不存在,而my_class由函数处理,则my_function.default始终存在且总是会在这些情况下调用。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-02
相关资源
最近更新 更多