R:如何找到将在对象上调用的 S3 方法? [英] R: how to find what S3 method will be called on an object?

查看:16
本文介绍了R:如何找到将在对象上调用的 S3 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 methods(),它返回给定类的所有方法.假设我有 x 并且我想知道当我调用 foo(x) 时会调用什么方法.有没有可以做到这一点的单线或包裹?

I know about methods(), which returns all methods for a given class. Suppose I have x and I want to know what method will be called when I call foo(x). Is there a oneliner or package that will do this?

我能想到的最短的是:

sapply(class(x), function(y) try(getS3method('foo', y), silent = TRUE))

然后检查结果的类...但是没有内置的吗?

and then to check the class of the results... but is there not a builtin for this?

更新

完整的一个班轮将是:

fm <- function (x, method) { 
  cls <- c(class(x), 'default')
  results <- lapply(cls, function(y) try(getS3method(method, y), silent = TRUE))
  Find(function (x) class(x) != 'try-error', results)   
}

这适用于大多数情况,但请注意,对于某些复杂的对象,它可能会失败.例如,根据 ?S3Methods,在 matrix(1:4, 2, 2) 上调用 foo 会尝试 foo.matrix,然后是 foo.numeric,然后是 foo.default;而此代码将只查找 foo.matrixfoo.default.

This will work with most things but be aware that it might fail with some complex objects. For example, according to ?S3Methods, calling foo on matrix(1:4, 2, 2) would try foo.matrix, then foo.numeric, then foo.default; whereas this code will just look for foo.matrix and foo.default.

推荐答案

findMethod 下面定义的不是单行代码,但它的主体只有 4 行代码(如果我们要求泛型作为字符串传递,它可以减少到 3 行代码).它将返回一个字符串,该字符串表示输入泛型将分派的方法名称,给定泛型及其参数.(如果您想返回方法本身,请将 findMethod 主体的最后一行替换为 get(X(...)).)在内部它创建了一个泛型X 和对应于输入泛型的每个方法的 X 方法,以便每个 X 方法返回将运行的输入泛型的方法的名称.X 泛型及其方法都是在 findMethod 函数中创建的,因此它们在 findMethod 退出时消失.为了得到结果,我们只需将输入参数作为 findMethod 函数体的最后一行运行 X.

findMethod defined below is not a one-liner but its body has only 4 lines of code (and if we required that the generic be passed as a character string it could be reduced to 3 lines of code). It will return a character string representing the name of the method that would be dispatched by the input generic given that generic and its arguments. (Replace the last line of the body of findMethod with get(X(...)) if you want to return the method itself instead.) Internally it creates a generic X and an X method corresponding to each method of the input generic such that each X method returns the name of the method of the input generic that would be run. The X generic and its methods are all created within the findMethod function so they disappear when findMethod exits. To get the result we just run X with the input argument(s) as the final line of the findMethod function body.

findMethod <- function(generic, ...) {
  ch <- deparse(substitute(generic))
  f <- X <- function(x, ...) UseMethod("X")
  for(m in methods(ch)) assign(sub(ch, "X", m, fixed = TRUE), "body<-"(f, value = m))
  X(...)
}

现在测试一下.(请注意,问题中的单行代码在其中几个测试中失败并出现错误,但 findMethod 给出了预期的结果.)

Now test it. (Note that the one-liner in the question fails with an error in several of these tests but findMethod gives the expected result.)

findMethod(as.ts, iris)
## [1] "as.ts.default"

findMethod(print, iris)
## [1] "print.data.frame"

findMethod(print, Sys.time())
## [1] "print.POSIXct"

findMethod(print, 22)
## [1] "print.default"

# in this example it looks at 2nd component of class vector as no print.ordered exists
class(ordered(3))
## [1] "ordered" "factor" 
findMethod(print, ordered(3))
## [1] "print.factor"

findMethod(`[`, BOD, 1:2, "Time")
## [1] "[.data.frame"

这篇关于R:如何找到将在对象上调用的 S3 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆