UseMethod()vs inherits()确定R中对象的类 [英] `UseMethod()` vs `inherits()` to determine an object's class in R

查看:275
本文介绍了UseMethod()vs inherits()确定R中对象的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我需要根据它们的类以不同的方式处理R对象,则可以使用 if else 在单个函数中:

If I need to treat R objects in different ways according to their class, I can either use if and else within a single function:

foo <- function (x) {
  if (inherits(x, 'list')) {
    # Foo the list
  } else if (inherits(x, 'numeric')) {
    # Foo the numeric
  } else {
    # Throw an error
  }
}

或者我可以定义一个方法:

Or I can define a method:

foo <- function (x) UseMethod('foo')

foo.list <- function (x) {
  # Foo the list
}
foo.numeric <- function (x) {
  # Foo the numeric
}

每种方法的优点是什么?对性能有影响吗?

What are the advantages to each approach? Are there performance implications?

推荐答案

好,我认为有一些背景知识可以回答这个问题。

OK, there is some background to be covered to answer this question (in my view)...

在R中,如果您具有用户定义的对象结构或对象(例如因子向量或数据框)以及其他属性,则该对象的类是显式的在对象本身的处理中起着重要的作用-例如,因子向量的级别标签或数据框中的变量名称是可修改的属性,在访问每个对象的观察结果时起主要作用。

Within R, the class of an object is explicit in situations where you have user-defined object structures or an object such as a factor vector or data frame where other attributes play an important part in the handling of the object itself—for example, level labels of a factor vector, or variable names in a data frame, are modifiable attributes that play a primary role in accessing the observations of each object.

但是,请注意,基本的R对象(例如向量,矩阵和数组)是隐式分类的,这意味着该类未使用attribute函数标识。无论是隐式还是显式,始终可以使用特定于属性的函数类来检索给定对象的类。

当泛型函数 foo 应用于具有类属性c( first, second)的对象,系统搜索名为foo的函数.first,如果找到它,则将其应用于对象。如果找不到这样的函数,则尝试一个名为 foo.second 的函数。如果没有任何类名生成合适的函数,则使用函数 foo.default (如果存在)。如果没有类属性,则尝试使用隐式类,然后使用 default 方法。

When a generic function foo is applied to an object with class attribute c("first", "second"), the system searches for a function called foo.first and, if it finds it, applies it to the object. If no such function is found, a function called foo.second is tried. If no class name produces a suitable function, the function foo.default is used (if it exists). If there is no class attribute, the implicit class is tried, then the default method.

函数类输出对象继承的类的名称的向量。

The function class prints the vector of names of classes an object inherits from.

class <-设置对象继承的类。

inherits()指示其第一个参数是否继承自 what 参数中指定的任何类。 方法分派基于泛型函数的第一个参数的类进行。如果它为TRUE,则一个整数向量,其长度与返回的长度相同。每个元素指示在类别(x)中与what元素匹配的位置;零表示没有匹配项。如果这是FALSE,则与任何类匹配的任何名称都将通过继承返回TRUE。

inherits() indicates whether its first argument inherits from any of the classes specified in the what argument. Method dispatch takes place based on the class of the first argument to the generic function. If which is TRUE then an integer vector of the same length as what is returned. Each element indicates the position in the class(x) matched by the element of what; zero indicates no match. If which is FALSE then TRUE is returned by inherits if any of the names in what match with any class.

inherits()外,所有其他名称都是

All but inherits() are primitive functions.

好的,现在让我们以相反的顺序考虑您的示例...

OK, so let us now consider your examples in reverse order...

foo <- function (x) UseMethod('foo')

foo.list <- function (x) {
  # Foo the list
}
foo.numeric <- function (x) {
  # Foo the numeric
}

现在我们是否使用函数method()

now if we use the function methods()

methods(foo)
[1] foo.list    foo.numeric
see '?methods' for accessing help and source code
> getS3method('foo','list')
function (x) {
  # Foo the list
}

因此我们有一个类 foo 和两个关联的方法 foo.list foo.numeric 。因此,我们现在知道 foo 类具有支持 list 数字的方法。 code>操作。

thus we have a class foo and two associated methods foo.list and foo.numeric. Thus, we now know that class foo, has methods to support list and numeric operations.

好,现在让我们考虑您的第一个示例...

OK, now let's consider your first example...

function (x) {
  if (inherits(x, 'list')) {
    # Foo the list
    print(paste0("List: ", x))
  } else if (inherits(x, 'numeric')) {
    # Foo the numeric
    print(paste0("Numeric: ", x))
  } else {
    # Throw an error
    print(paste0("Unhandled - Sorry!"))
  }
}

问题是这不是s3类,而是R函数。如果对 foo 运行 methods(),它将返回未找到方法

the problem is that this is not an s3 class, it is an R function. If you run methods() against foo it returns "no methods found"

> methods(foo)
no methods found
> getS3method('foo','list')
Error in getS3method("foo", "list") : no function 'foo' could be found

那么第二个例子中发生了什么? Inherits()操作与参数的类匹配。 Inherits()-> 方法分配是基于泛型函数的第一个参数的类进行的。

so what is happening in the second example? The inherits() operation is matching the class of the parameter. inherits() -> Method dispatch takes place based on the class of the first argument to the generic function.

所以您的第一个示例很简单在函数参数x 的类中查找,没有创建或存在任何S3类。

So your first example is simply looking up the class of the function argument x, no S3 class is created or exists.

好,我对此有偏见,但是对象的类是描述R中实体的最有用的属性之一。 ,至少包含一个类的隐式或显式。 R是一种面向对象的编程语言,意味着实体存储为对象并具有作用于它们的方法。

OK, I am biased here but an object’s class is one of the most useful attributes for describing an entity in R. Every object you create is identified, either implicitly or explicitly, with at least one class. R is an object-oriented programming language, meaning entities are stored as objects and have methods that act upon them.

第二种方法是我认为的方法。为什么?因为您确实在按预期使用语言构造。显式使用Inherits()的第一种方法感觉很像黑客。从我个人的角度来看,可读性是理解的关键,因此我担心阅读第一个示例的人可能会被问到一个问题:他们(程序员)为什么采用这种方法,我想念的是什么?。然后,我担心的是要避免复杂性,因为它会妨碍代码理解。因此,保持简单有利于代码理解。

So the second approach is the way to go in my opinion. Why? Because you are truly using the language construct as intended. The first approach where you use inherits() explicitly feels like a hack. Readability is key to comprehension from my personal perspective, thus I worry that a person reading the first example might be led to ask the question "Why did they (the programmer) take said approach, what am I missing?". My concern then is that complexity is to be avoided as it can impede code comprehension. Thus, keep it simple is advantageous to code comprehension.

关于代码性能,if-else解析器通常比对象查找模型要快,尽管查找模型并不等同于类映射过程,所以我觉得在这种情况下,性能问题很难回答。为什么?两种方法是不同的

In reference to code performance, an if-else parser is generally going to be faster than an object lookup model though a lookup model is not equivalent to a class mapping process so I feel the performance question is tricky to answer in this context. Why? The two approaches are different.

我希望以上内容为您指出正确的方向。保持安全,良好的业力向您飞来。

I hope the above points you in the right direction. Stay safe, good karma flying your way.

此处有一些推荐书籍:


  1. Patrick Burns的R地狱

  2. Hadley Wickham的Advanced R

  3. R for所有人:高级分析和图形

这篇关于UseMethod()vs inherits()确定R中对象的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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