理解attr(x,"class")和class(x)之间的区别

Kon*_*rad 10 oop primitive r class

背景

我正在看RomainFrançois提出的爵士乐套餐.Romain is_bare_vector使用以下语法定义函数:

is_bare_vector <- function(x) {
  is_vector(x) && !is.object(x) && is.null(attr(x, "class"))
}
Run Code Online (Sandbox Code Playgroud)

对于x <- 1:

attr(x, "class")
# NULL
Run Code Online (Sandbox Code Playgroud)

鉴于:

class(x)
# [1] "numeric"
Run Code Online (Sandbox Code Playgroud)

我想理解为什么这两个函数提供不同的答案??attr参考文献的帮助?class

?attr

请注意,一些属性(即class,comment,dim,dimnames, names,row.namestsp)都是经过特殊处理的,并具有可在其上设置的值的限制.(请注意,对于通过级别替换功能应为因子设置的级别,情况并非如此.)

?class

许多R对象都有一个class属性,一个字符向量给出了对象继承的类的名称.(函数 oldClassoldClass<-获取和设置属性,也可以直接完成.)

duc*_*ayr 8

您只需要进一步阅读help("class"):

如果对象没有class属性,它有一个隐式类,特别是"matrix","array","function"或"numeric"或者typeof(x)的结果(类似于mode(x))

class()如果class属性显然也会返回隐式类NULL; 让我们检查C源代码 - 我们看到如果class属性的长度为0,它将获得隐式类:

SEXP R_data_class(SEXP obj, Rboolean singleString)
{
    SEXP value, klass = getAttrib(obj, R_ClassSymbol);
    int n = length(klass);
    if(n == 1 || (n > 0 && !singleString))
    return(klass);
    if(n == 0) {
    SEXP dim = getAttrib(obj, R_DimSymbol);
    int nd = length(dim);
    if(nd > 0) {
        if(nd == 2)
        klass = mkChar("matrix");
        else
        klass = mkChar("array");
    }
    else {
      SEXPTYPE t = TYPEOF(obj);
      switch(t) {
      case CLOSXP: case SPECIALSXP: case BUILTINSXP:
        klass = mkChar("function");
        break;
      case REALSXP:
        klass = mkChar("numeric");
        break;
      case SYMSXP:
        klass = mkChar("name");
        break;
      case LANGSXP:
        klass = lang2str(obj, t);
        break;
      default:
        klass = type2str(t);
      }
    }
    }
    else
    klass = asChar(klass);
    PROTECT(klass);
    value = ScalarString(klass);
    UNPROTECT(1);
    return value;
}
Run Code Online (Sandbox Code Playgroud)