is和inherits有什么区别?

32 浏览
0 Comments

is和inherits有什么区别?

如果我想要检查一个变量是否继承自某个类,我可以使用isinherits

class(letters)
## [1] "character"
is(letters, "character")
## [1] TRUE
inherits(letters, "character")
## [1] TRUE

有没有对我应该使用哪一个更偏好的建议,它们是否会返回不同的值?

0
0 Comments

is()和inherits()是用于测试对象类型的两个函数。根据给出的答案,我进行了以下操作:

- 创建了不同类型的R对象

- 使用storage.mode()、mode()、typeof()和class()提取了这些对象的类型

- 使用is()、inherits()和is.*()来测试这些对象是否属于返回的类型

以下是上述三个步骤的一个小例子:

# 使用storage.mode()、mode()、typeof()和class()获取对象的类别
obj <- logical()
(types <- c(storage.mode= storage.mode(obj),
            mode= mode(obj),
            type= typeof(obj),
            class= class(obj)))
storage.mode         mode         type        class
    "double"    "numeric"     "double"    "numeric"
# 使用is、inherits和is.*来测试返回的类型
> is(obj, "double"); is(obj, "numeric")
[1] FALSE
[1] TRUE
> inherits(obj, "double"); inherits(obj, "numeric")
[1] FALSE
[1] TRUE
> is.double(obj); is.numeric(obj)
[1] TRUE
[1] TRUE

现在我们使用以下代码对一组对象类型进行相同的操作:

# 生成不同类型的对象
library(xml2)
setClass("dummy", representation(x="numeric", y="numeric"))
obj <- list(
  "logical vector" = logical(),
  "integer vector" = integer(),
  "numeric vector" = numeric(),
  "complex vector" = complex(),
  "character vector" = character(),
  "raw vector" = raw(),
  "factor" = factor(),
  "logical matrix" = matrix(logical()),
  "numeric matrix" = matrix(numeric()),
  "logical array" = array(logical(8), c(2, 2, 2)),
  "numeric array" = array(numeric(8), c(2, 2, 2)),
  "list" = list(),
  "pairlist" = .Options,
  "data frame" = data.frame(),
  "closure function" = identity,
  "builtin function" = `+`,
  "special function" = `if`,
  "environment" = new.env(),
  "null" = NULL,
  "formula" = y ~ x,
  "expression" = expression(),
  "call" = call("identity"),
  "name" = as.name("x"),
  #"paren in expression" = expression((1))[[1]], # Code fails with this
  #"brace in expression" = expression({1})[[1]], # Code fails with this
  "S3 lm object" = lm(dist ~ speed, cars),
  "S4 dummy object" = new("dummy", x = 1:10, y = rnorm(10)),
  "external pointer" = read_xml("")$node
)
# 提取类型并进行测试
res <- do.call("rbind.data.frame", Map(function(x, name){
  types <- c(storage.mode= storage.mode(x),
                mode= mode(x),
                type= typeof(x),
                class= class(x))
  data.frame("object"= name,
             "extract_method"= names(types),
             "extract_result"= types,
             "inherits"= sapply(types, function(i) inherits(x, i)),
             "is"= sapply(types, function(i) is(x, i)),
             "is.type"= sapply(types, function(i) eval(parse(text= paste0("tryCatch({is.", i, "(x)}, error= function(e){'is.", i, "() does not exist'})"))))
  )}, obj, names(obj)))
rownames(res) <- 1:nrow(res)
res <- res[order(res$extract_method), ]

我们可以从结果`res`中获得一些见解。例如,我们可以查看`is.()`与`inherits()`不返回相同结果的情况:

> res[res$inherits != res$is, ]
           object extract_method extract_result inherits   is is.type
6  integer vector           mode        numeric    FALSE TRUE TRUE
87           call   storage.mode       language    FALSE TRUE TRUE
89           call           type       language    FALSE TRUE TRUE

当然,结果还显示了更多信息,例如我们可以看到`inherits()`在返回的类型中返回`FALSE`的情况,等等。在这里我省略了这些内容。实际上,我认为我的答案更广泛,因为它考虑了提取和测试对象类型的差异。通过阅读了很多关于对象类型的资料,我得出了上面的代码,并希望与大家分享。然而,仅使用`res[res$inherits != res$is, ]`就可以回答这个问题。

0
0 Comments

短版:

大部分情况下使用inherits,但在处理数字和S4类时要小心。


长版:

is帮助页面的“See Also”部分:

inherits对于S4和非S4对象几乎总是等效于is,并且速度稍快。不等价的情况是在具有条件超类的类中,关系中有非平凡的测试(不常见且不建议使用):对于这些情况,is测试关系,但inherits按定义忽略S4对象的条件继承。

inherits帮助页面的“Formal Classes”部分:

正式类的inherits的类似函数是is。这两个函数的行为一致,除了一个例外:S4类可以具有条件继承和显式测试。在这种情况下,is将测试条件,但inherits将忽略所有条件超类。

所以它们大部分情况下返回相同的结果,但是inherits更快,所以在大多数情况下应该是默认选择。(正如Konrad所提到的,is还需要加载methods包,这可能使其在性能敏感的Rscript使用中不适用。)

如果您使用具有条件继承的S4类,这两个函数的返回值可能会有所不同,但这是不推荐的(请参阅“方法选择和调度:详细信息”部分),这意味着这种情况可能很少见。

两个函数最明显的区别在于检查整数是否为数值类型。

class(1L)
## [1] "integer"
is.numeric(1L)
## [1] TRUE
is(1L, "numeric")
## [1] TRUE
inherits(1L, "numeric")
## [1] FALSE

那么,你能解释一下为什么整数不会“继承”,而浮点数会吗? Rgames> class(1.4) [1] "numeric" Rgames> is.numeric(1.4) [1] TRUE Rgames> inherits(1.4,'numeric') [1] TRUE Rgames> is(1.4,'numeric') [1] TRUE

我认为这可能与数值对象只有一个隐式类有关:从?class如果对象没有类属性,则具有隐式类“"matrix"”、“"array"”或“mode(x)”的结果(除了整数向量具有隐式类“"integer"”)。我可以想象(??)is关注隐式类而inherits则不关注...?

我记得听说过一位高级R专家称这为“不幸之处”。

另一个非常关键的区别是ismethods包中的函数,默认情况下在运行Rscript时不加载该包(因为加载速度慢)。相比之下,inherits来自base,因此在R脚本程序中可以直接使用。

0