使用R属性有什么危险?

使用R属性有什么危险?,r,R,将使用过的定义属性添加到R对象中,可以很容易地携带与感兴趣的对象粘在一起的一些附加信息。问题在于,它略微改变了R对对象的看法,例如,具有附加属性的数值向量仍然是数值,但不再是向量: x <- rnorm(100) class(x) ## [1] "numeric" is.numeric(x) ## [1] TRUE is.vector(x) ## [1] TRUE mode(x) ## [1] "numeric" typeof(x) ## [1] "double" attr(x, "foo

将使用过的定义属性添加到R对象中,可以很容易地携带与感兴趣的对象粘在一起的一些附加信息。问题在于,它略微改变了R对对象的看法,例如,具有附加属性的数值向量仍然是
数值
,但不再是
向量

x <- rnorm(100)
class(x)
## [1] "numeric"
is.numeric(x)
## [1] TRUE
is.vector(x)
## [1] TRUE
mode(x)
## [1] "numeric"
typeof(x)
## [1] "double"
attr(x, "foo") <- "this is my attribute"
class(x)
## [1] "numeric"
is.numeric(x)
## [1] TRUE
is.vector(x)
## [1] FALSE  # <-- here!
mode(x)
## [1] "numeric"
typeof(x)
## [1] "double"
x在我(有点有限)的经验中,向对象添加新属性从未破坏任何东西。我能想到的唯一可能的情况是,如果一个函数要求一个对象具有一组特定的属性,而不要求其他属性,那么它将破坏某些东西。但我想不出有哪一次我遇到过这种情况。大多数函数,尤其是S3方法中的函数,只会忽略它们不需要的属性

如果删除属性,则更可能出现问题

您不会看到由于附加属性而产生很多问题的原因是,方法是在对象的
类上调度的。只要类不发生更改,方法的调度方式就基本相同。然而,这并不意味着现有方法将知道如何处理新属性。以下面的示例为例--在向
x
y
添加一个
new\u attr
属性后,然后再添加它们,结果采用
x
属性。
y
的属性发生了什么变化?默认的
+
函数不知道如何处理同名的冲突属性,因此它只接受第一个属性(更多详细信息,请访问,谢谢Brodie)

另一方面,
mean(x)
甚至不尝试保留属性。我不知道有什么好方法可以预测哪些函数会保留属性,哪些函数不会保留属性。在BaseR中可能会用到一些可靠的助记符(聚合还是向量化?),但我认为有一个单独的原则需要考虑

如果保留新属性很重要,则应定义一个新类来保留旧类的继承性

通过一个新类,您可以编写扩展泛型的方法,并以您想要的任何方式处理属性。您是否应该定义一个新类并编写它的方法,这在很大程度上取决于您添加的任何新属性对将来的工作有多大价值


因此,一般来说,添加新属性不太可能破坏R中的任何内容。但是如果不添加新的类和方法来处理新属性,我会非常谨慎地在这些属性通过其他函数后解释它们的含义。

来自
?is.vector
,“如果x是指定模式的向量,除名称外没有其他属性,则is.vector返回TRUE。注意,
是.atomic(x)
仍然返回
TRUE
。对于添加了属性的对象,我最担心的是某些函数会剥离这些属性,而且剥离属性的时间并不总是可以预测的。@Benjamin这正是我要问的:)我想让它更精确地说明什么是“某些”“有时”的情况,以及它们可能有多糟糕。失去属性就不那么重要了,我想问的是它是否能阻止任何事情?你能提供更多关于预期用例的细节吗?您会将属性附加到各种不同类型的对象上吗?在什么情况下你会这样做?你将如何使用它们?就目前而言,这个问题有可能因为“过于宽泛”而被关闭。@BrodieG我想我已经提到了所有的事情:(1)用它们来携带信息以便以后阅读;(2) 将它们附加到标准的R对象(向量、矩阵、数据帧等),(3)在任何情况下-我想使其成为一般性的;(4) 我想保存一些信息(例如使用的随机种子)并在以后阅读。另外,属性发生什么的规范参考:
x <- 1:10
y <- 10:1

attr(x, "new_attr") <- "yippy"
attr(y, "new_attr") <- "ki yay"

x + y

[1]  1  2  3  4  5  6  7  8  9 10
attr(,"new_attr")
[1] "yippy"
x <- 1:10
y <- 10:1

attr(x, "new_attr") <- "yippy"
attr(y, "another_attr") <- "ki yay"

x + y
 [1] 11 11 11 11 11 11 11 11 11 11
attr(,"another_attr")
[1] "ki yay"
attr(,"new_attr")
[1] "yippy"