使用R属性有什么危险?

Tim*_*Tim 13 r

将已使用定义的属性添加到R​​对象可以很容易地携带与感兴趣对象粘合在一起的一些附加信息.问题是它稍微改变了R看到对象的方式,例如具有附加属性的数字向量仍然是numericvector不再是:

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"
Run Code Online (Sandbox Code Playgroud)

这会导致任何潜在的问题吗?我正在考虑的是向常见的R对象添加一些属性,然后将它们传递给其他方法.仅因为我在标准R对象中添加了额外属性(例如矢量,矩阵,数据帧等)这一事实,有什么东西可以破坏?

请注意,我不是要求创建自己的类.为简单起见,我们还可以假设属性名称中没有任何冲突(例如使用dims属性).让我们假设如果某些方法在某些方面会使我的属性失效,那就不是问题,这是一个可接受的风险.

Ben*_*min 12

在我的(有限的)体验中,对象添加新属性并没有破坏任何东西.我能想到的唯一可能的情况是,如果一个函数需要一个对象具有一组特定的属性而没有别的东西.我想不出有一次我遇到过那个.大多数函数,特别是在S3方法中,只会忽略它们不需要的属性.

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

您不会看到源于其他属性的许多问题的原因是方法是在class对象上调度的.只要类没有改变,方法将以大致相同的方式发送.但是,这并不意味着现有方法将知道如何处理新属性.看看下面的例子-添加后new_attr属性不仅可以xy,然后加入他们,结果采用的属性x.属性发生了什么变化y?默认+函数不知道如何处理同名的冲突属性,所以它只需要第一个(R语言定义的更多细节,感谢Brodie).

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"
Run Code Online (Sandbox Code Playgroud)

在不同的例子,如果我们放弃x,并y以不同的名称属性,x + y产生了保留这两个属性的对象.

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"
Run Code Online (Sandbox Code Playgroud)

另一方面,mean(x)甚至没有尝试保留属性.我不知道预测哪些函数将保留属性和不保留属性的好方法.你可以在基础R中使用一些可靠的助记符(聚合与矢量化,也许?),但我认为应该考虑一个单独的原则.

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

使用新类,您可以编写扩展泛型的方法,并以您想要的任何方式处理属性.是否应该定义新类并编写其方法在很大程度上取决于您添加的任何新属性对您将要执行的未来工作的价值.

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

  • 此外,关于属性发生的规范参考:[R-lang定义](https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Copying-of-attributes) (4认同)