即使过度分配,也可以检索原始版本的包功能

标签 r

假设我替换了一个包的函数,例如 knitr:::sub_ext .
(注意:我对它是内部函数的地方特别感兴趣,即只能由 ::: 访问,而不是 :: ,但相同的答案可能适用于两者)。

library(knitr)
my.sub_ext <- function (x, ext) {
    return("I'm in your package stealing your functions D:")
}
# replace knitr:::sub_ext with my.sub_ext
knitr <- asNamespace('knitr')
unlockBinding('sub_ext', knitr)
assign('sub_ext', my.sub_ext, knitr)
lockBinding('sub_ext', knitr)

问题:有没有办法找回原来的knitr:::sub_ext在我做完这件事之后?最好不重新加载包?

(我知道有些人想知道我为什么要这样做,所以在这里。不需要阅读该问题)。我一直在修补这样的包中的一些功能(实际上不是 sub_ext 功能......):
original.sub_ext <- knitr:::sub_ext
new.sub_ext <- function (x, ext) {
    # some extra code that does something first, e.g.
    x <- do.something.with(x)
    # now call the original knitr:::sub_ext
    original.sub_ext(x, ext)
}
# now set knitr:::sub_ext to new.sub_ext like before.

我同意这通常不是一个好主意(在大多数情况下,这些都是快速修复,直到更改进入 CRAN,或者它们是永远不会被批准的“功能请求”,因为它们在某种程度上是特定于案例的)。

上面的问题是如果我不小心执行了两次(例如,它在我运行两次的脚本的顶部,中间没有重新启动 R),第二次 original.sub_ext其实是以前的new.sub_ext与真实的knitr:::sub_ext相反,所以我得到无限递归。

sub_ext是一个内部函数(我不会直接调用它,但是像 knit 这样的 knitr 函数都在内部调用它),我不能希望修改所有调用 sub_ext 的函数调用 new.sub_ext手动,因此是替换包命名空间中定义的方法。

最佳答案

当您这样做时assign('sub_ext', my.sub_ext, knitr) ,您将不可撤销地覆盖以前与 sub_ext 关联的值值为 my.sub_ext .但是,如果您首先存储原始值,完成后重置它并不难:

library(knitr)
knitr <- asNamespace("knitr")

## Store the original value of sub_ext
.sub_ext <- get("sub_ext", envir = knitr)

## Overwrite it with your own function
my.sub_ext <- function (x, ext) "I'm in your package stealing your functions D:"
assignInNamespace('sub_ext', my.sub_ext, knitr)
knitr:::sub_ext("eg.csv", "pdf")
# [1] "I'm in your package stealing your functions D:"

## Reset when you're done
assignInNamespace('sub_ext', .sub_ext, knitr)
knitr:::sub_ext("eg.csv", "pdf")
# [1] "eg.pdf"   

或者 ,只要您只是将代码行添加到已经存在的代码中,您就可以使用 trace() 添加该代码。 .有什么好处trace()也就是说,当你完成后,你可以使用 untrace()将函数的主体恢复为其原始形式:
trace(what = "mean.default", 
      tracer = quote({
          a <- 1
          b <- 2
          x <- x*(a+b)
      }), 
      at = 1)
mean(1:2)
# Tracing mean.default(1:2) step 1 
# [1] 4.5
untrace("mean.default")
# Untracing function "mean.default" in package "base"
mean(1:2)
# [1] 1.5

请注意,如果您要跟踪的函数位于命名空间中,则您需要使用 trace()where参数,将共享待跟踪函数命名空间的其他(导出)函数的名称传递给它。因此,要跟踪 中未导出的函数针织 的命名空间,你可以设置 where=knit

关于即使过度分配,也可以检索原始版本的包功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16473795/

相关文章:

r - ggplot2密度绘制R中不同大小的数据

r - 给定向量长度的向量到 r 中的数据帧

r - 创建新的数据框,其中变量在特定时期内每年增长

r - ggplot2 绘图区域边距?

r - 如何计算两个字符串向量之间的余弦相似度

sql - 使用 sqldf 保留时间类

R条件过滤器

r - 用正值和负值标记堆叠条形图

r - 按列模式和绑定(bind)行拆分 data.frame R

r - 在 R 中自动过滤测量数据