1.3 属性

Keywords:

Next: ,Previous: Environments and variable lookup,Up: R Internal Structures

1.3 属性

正如我们所见,每个 SEXPREC 都有一个指针指向节点的属性(默认是R_NilValue)。属性可以通过宏/函数ATTRIBSET_ATTRIB访问/设置。但是,直接访问通常仅用于检验属性是否为NULL或者重新设置它们。另外访问可以利用对属性增加约束的函数getAttribsetAttrib。 一个值得关注的地方是,如果你把一个对象的属性拷贝给另外一个对象,你可能需要设置"class"属性,而且还需要拷贝这个对象和S4二进制位(S4 bits)。宏/函数DUPLICATE_ATTRIB 可以自动完成这些工作。

在代码中,假定一个节点的属性要么是R_NilValue,要么是一个长度不是0的成对列表(被 SET_ATTRIB 所检验)。属性需要命名(通过成对列表的标签命名)。置换函数 attributes<- 保证"dim" 在成对列表中在 "dimnames"之前。"dim" 属性是几个特别处理的属性之一:值会被检验,任何"names""dimnames" 属性都会被去掉。因此,在设置 "dim" 前是不能设置"dimnames" 属性的,并且被分配的值必须是有正确长度的列表(元素的长度也必须正确,长度为0的元素用NULL替换)。

其它被特别处理的属性包括"names""class""tsp""comment""row.names"。对于成对列表类似的对象,名字不是以属性的方式而是以标签的方式(也是符号)保存:但是 R 的接口使它们和常规的属性非常相似,并且对于一维数组,它们作为"dimnames"属性的第一个元素保存。C代码保证 "tsp" 属性是一种REALSXP,频率是正数和暗含的长度吻合被分配对象的行数。类和注释限制在字符向量,而长度为0的注释或类会移除该属性的。设置或去掉 "class" 属性会适当地设定一个对象的二进制位(Object Bit)。整数行名字可以和内置的紧凑描述方式相互转换。

给一个拥有非标准复制语义(copying semantics)的类型的对象增加属性的时候,需要特别小心。NILSXP类型只有一个对象R_NilValue,并且它没有任何属性(这是在installAttrib强制要求的)。对于环境,外部指针和弱引用(weak reference),属性必须和对象的所有使用相关:比如一个环境有名字,和一个包里面的 R 代码相关的环境有一个"path" 属性是合理的。

什么时候需要在对象操作时保留属性呢?Becker, Chambers & Wilks (1988, pp. 144–6) 给予了一些意见。标量函数(指的是在向量运算中的逐个元素逐个元素地操作而且输出格式类似输入格式)必须保留属性(可能类另外,若它们保留类则它们需要保留 OBJECT 和 S4 二进制位)。二元运算通常调用copyMostAttributes 来拷贝长参数的大部分属性(如果二者的长度都是一样的,优先采用第一个参数的值)。这里 `大多数' 表示除代码中为运算适当保留的 namesdimdimnames属性外的所有属性。

子集操作(不同于空的索引)通常丢弃除适当设置的namesdimdimnames 外的所有属性。另外一方面,子赋值通常保留这些属性,即使长度已经发生变化。可以强制抛弃所有的属性。比如:

     > x <- structure(1:8, names=letters[1:8], comm="a comment")

     > x[]

     a b c d e f g h

     1 2 3 4 5 6 7 8

     attr(,"comm")

     [1] "a comment"

     > x[1:3]

     a b c

     1 2 3

     > x[3] <- 3

     > x

     a b c d e f g h

     1 2 3 4 5 6 7 8

     attr(,"comm")

     [1] "a comment"

     > x[9] <- 9

     > x

     a b c d e f g h

     1 2 3 4 5 6 7 8 9

     attr(,"comm")

     [1] "a comment"

Hits:Loading...

special topic