-->

我怎样才能查看功能的源代码?(How can I view the source code for

2019-10-22 06:52发布

我想看看源代码的功能,看看它是如何工作的。 我知道我可以在提示符下输入其名称打印功能:

> t
function (x) 
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>

在这种情况下,什么是UseMethod("t")是什么意思? 如何找到这实际上是正在使用的源代码,例如: t(1:10)

有没有当我看到之间的差异UseMethod ,当我看到standardGenericshowMethods ,与with

> with
standardGeneric for "with" defined from package "base"

function (data, expr, ...) 
standardGeneric("with")
<bytecode: 0x102fb3fc0>
<environment: 0x102fab988>
Methods may be defined for arguments: data
Use  showMethods("with")  for currently available ones.

在其他情况下,我可以看到的是,R函数被调用,但我不能找到这些功能的源代码。

> ts.union
function (..., dframe = FALSE) 
.cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE)
<bytecode: 0x36fbf88>
<environment: namespace:stats>
> .cbindts
Error: object '.cbindts' not found
> .makeNamesTs
Error: object '.makeNamesTs' not found

如何找到喜欢的功能.cbindts.makeNamesTs

在另一些情况下,有一点R代码里面,但大部分的工作似乎是在其他地方进行。

> matrix
function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL) 
{
    if (is.object(data) || !is.atomic(data)) 
        data <- as.vector(data)
    .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), 
        missing(ncol)))
}
<bytecode: 0x134bd10>
<environment: namespace:base>
> .Internal
function (call)  .Primitive(".Internal")
> .Primitive
function (name)  .Primitive(".Primitive")

我如何找出什么.Primitive功能呢? 同样,一些函数调用.C.Call.Fortran.External ,或.Internal 。 我如何才能找到这些源代码?

Answer 1:

UseMethod("t")是告诉你, t()是( S3具有对不同的对象类的方法)的通用功能。

的S3方法调度系统

对于S3类,你可以使用methods功能列出特定泛型函数或类的方法。

> methods(t)
[1] t.data.frame t.default    t.ts*       

   Non-visible functions are asterisked
> methods(class="ts")
 [1] aggregate.ts     as.data.frame.ts cbind.ts*        cycle.ts*       
 [5] diffinv.ts*      diff.ts          kernapply.ts*    lines.ts        
 [9] monthplot.ts*    na.omit.ts*      Ops.ts*          plot.ts         
[13] print.ts         time.ts*         [<-.ts*          [.ts*           
[17] t.ts*            window<-.ts*     window.ts*      

   Non-visible functions are asterisked

“非可视功能是带星号”指的是功能不从其包的命名空间导出。 仍然可以通过查看它的源代码:::功能(即stats:::t.ts ),或通过使用getAnywhere() getAnywhere()因为你不必知道该函数是从哪个包是非常有用的。

> getAnywhere(t.ts)
A single object matching ‘t.ts’ was found
It was found in the following places
  registered S3 method for t from namespace stats
  namespace:stats
with value

function (x) 
{
    cl <- oldClass(x)
    other <- !(cl %in% c("ts", "mts"))
    class(x) <- if (any(other)) 
        cl[other]
    attr(x, "tsp") <- NULL
    t(x)
}
<bytecode: 0x294e410>
<environment: namespace:stats>

S4的方法调度系统

该S4系统是一个较新的方法调度系统和是对S3系统的替代品。 下面是一个S4函数的一个例子:

> library(Matrix)
Loading required package: lattice
> chol2inv
standardGeneric for "chol2inv" defined from package "base"

function (x, ...) 
standardGeneric("chol2inv")
<bytecode: 0x000000000eafd790>
<environment: 0x000000000eb06f10>
Methods may be defined for arguments: x
Use  showMethods("chol2inv")  for currently available ones.

输出已经提供了大量的信息。 standardGeneric是S4功能的一个指标。 看到定义S4方法的方法提供有益:

> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"

getMethod可用于看到的方法之一的源代码:

> getMethod("chol2inv", "diagonalMatrix")
Method Definition:

function (x, ...) 
{
    chk.s(...)
    tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>

Signatures:
        x               
target  "diagonalMatrix"
defined "diagonalMatrix"

也有更复杂的签名的方法对于每个方法,例如

require(raster)
showMethods(extract)
Function: extract (package raster)
x="Raster", y="data.frame"
x="Raster", y="Extent"
x="Raster", y="matrix"
x="Raster", y="SpatialLines"
x="Raster", y="SpatialPoints"
x="Raster", y="SpatialPolygons"
x="Raster", y="vector"

看的源代码的这些方法的整个签名必须提供,例如一个

getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )

这将不足以供应部分签名

getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") : 
#  No method found for function "extract" and signature SpatialPolygons

调用未导出的函数功能

在的情况下ts.union.cbindts.makeNamesTs来自未导出函数stats命名空间。 可以通过使用视图的未导出函数的源代码:::操作者或getAnywhere

> stats:::.makeNamesTs
function (...) 
{
    l <- as.list(substitute(list(...)))[-1L]
    nm <- names(l)
    fixup <- if (is.null(nm)) 
        seq_along(l)
    else nm == ""
    dep <- sapply(l[fixup], function(x) deparse(x)[1L])
    if (is.null(nm)) 
        return(dep)
    if (any(fixup)) 
        nm[fixup] <- dep
    nm
}
<bytecode: 0x38140d0>
<environment: namespace:stats>

调用编译后的代码功能

需要注意的是由编译器创建包“编译”并非指字节编译R代码里面。 的<bytecode: 0x294e410>在上述输出线表示该功能是字节编译,并且仍然可以观看从R命令行源。

调用函数.C.Call.Fortran.External.Internal ,或.Primitive在编译的代码调用入口点,所以你必须看看编译代码的来源,如果你想充分了解该功能。 这将R源代码GitHub的反射镜是一个体面的地方开始。 功能pryr::show_c_source可以,因为它会直接带您到一个页面GitHub的一个有用的工具.Internal.Primitive电话。 包可以使用.C.Call.Fortran.External ; 但不.Internal.Primitive ,因为这些被用来调用内置转换为R解释功能。

调用上述的一些功能可以使用一个对象,而不是字符串的引用编译函数。 在这些情况下,该对象是类的"NativeSymbolInfo""RegisteredNativeSymbol" ,或"NativeSymbol" ; 和打印对象产生有用的信息。 例如, optim调用.External2(C_optimhess, res$par, fn1, gr1, con)注意,是C_optimhess ,不是"C_optimhess" optim是在统计数据包,这样你就可以键入stats:::C_optimhess看到有关的编译函数被调用的信息。

在一个包已编译代码

如果你想在一个包来查看编译的代码,你需要下载/解压缩包源。 安装的二进制文件是不够的。 一个包的源代码可以从相同的CRAN(或CRAN兼容),该软件包最初是从安装库。 该download.packages()函数可以得到包源为您服务。

download.packages(pkgs = "Matrix", 
                  destdir = ".",
                  type = "source")

这将下载矩阵包的源版本,并保存相应.tar.gz文件在当前目录中。 对编译函数的源代码可以在发现src未压缩和untared文件的目录。 的解压缩和untaring步骤可以的外部进行R ,或从内R使用untar()函数。 它可以下载和膨胀处理成一个单一的呼叫合并(注意,只有一个包在同一时间可以以这种方式被下载并解压):

untar(download.packages(pkgs = "Matrix",
                        destdir = ".",
                        type = "source")[,2])

或者,如果软件包开发是公开托管(例如,通过GitHub上 , R-伪造 ,或RForge.net ),你也许可以在线浏览源代码。

在碱包编译代码

某些包被认为是“基地”的包。 这些封装运送用R和它们的版本被锁定到R.实施例的版本包括basecompilerstats ,和utils 。 因此,它们不能用作在CRAN如上所述单独的可下载的软件包。 相反,它们是在根据单个包装体目录将R源树的一部分/src/library/ 。 如何访问将R源将在下一节中描述。

内置转换为R解释编译代码

如果您要查看内置到R解释的代码,你需要下载/解压将R来源; 或者您也可以通过R在线查看源代码Subversion版本库或温斯顿畅的github上镜 。

乌韦Ligges的ř新闻文章(PDF) (第43页)是如何查看源代码中的良好的一般参考.Internal.Primitive功能。 基本步骤是先寻找在函数名src/main/names.c ,然后搜索“C-条目”的名字在文件中src/main/*



Answer 2:

除了对这个问题和它的重复其他的答案,这里是得到一个包功能的源代码,而不必知道它是在哪个包的好方法例如,如果我们想为源。 randomForest::rfcv()

查看/在弹出窗口中编辑

edit(getAnywhere('rfcv'), file='source_rfcv.r')

重定向到一个单独的文件

capture.output(getAnywhere('rfcv'), file='source_rfcv.r')


Answer 3:

当您调试使用debug()函数它就会显现出来。 假设你想看到T中的底层代码()变调功能。 只是打字“T”,并没有太多透露。

>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>

但是,使用“调试(functionName)”,它揭示了底层代码,SAN的内部。

> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]> 
debugging in: t.ts(co2)
debug: {
    cl <- oldClass(x)
    other <- !(cl %in% c("ts", "mts"))
    class(x) <- if (any(other)) 
        cl[other]
    attr(x, "tsp") <- NULL
    t(x)
}
Browse[3]> 
debug: cl <- oldClass(x)
Browse[3]> 
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]> 
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>  
debug: attr(x, "tsp") <- NULL
Browse[3]> 
debug: t(x)

编辑:debugonce()完成相同的,而不必使用undebug()



Answer 4:

对于非原始功能,R基包括功能称为body()返回的函数的体。 例如,所述的源极print.Date()函数可以被看作:

body(print.Date)

会产生这样的:

{
    if (is.null(max)) 
        max <- getOption("max.print", 9999L)
    if (max < length(x)) {
        print(format(x[seq_len(max)]), max = max, ...)
        cat(" [ reached getOption(\"max.print\") -- omitted", 
            length(x) - max, "entries ]\n")
    }
    else print(format(x), max = max, ...)
    invisible(x)
}

如果您在脚本的工作,并希望该功能码为一个特征向量,就可以得到它。

capture.output(print(body(print.Date)))

将让你:

[1] "{"                                                                   
[2] "    if (is.null(max)) "                                              
[3] "        max <- getOption(\"max.print\", 9999L)"                      
[4] "    if (max < length(x)) {"                                          
[5] "        print(format(x[seq_len(max)]), max = max, ...)"              
[6] "        cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", "
[7] "            length(x) - max, \"entries ]\\n\")"                      
[8] "    }"                                                               
[9] "    else print(format(x), max = max, ...)"                           
[10] "    invisible(x)"                                                    
[11] "}"     

为什么我会想要做这样的事情? 我被创建自定义S3对象( x ,其中, class(x) = "foo"基于列表上)。 一个列表的成员(命名为“好玩”)是一个功能,我想print.foo()显示功能的源代码,缩进。 所以我结束了下面的代码片段print.foo()

sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0("      ", sourceVector, "\n"))

其缩进和显示与相关联的代码x[["fun"]]



Answer 5:

没有看到这如何适应主要答复的流量,但它难倒我了一段时间,所以我在这里将它:

中缀运算符

看到一些碱中缀运算符(例如,源代码%%%*% %in% ),使用getAnywhere ,例如:

getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
#   package:base
#   namespace:base
#  with value
#
# function (e1, e2)  .Primitive("%%")

主要的答案包括如何再使用镜子进行深入分析。



Answer 6:

有R中一个非常方便的功能edit

new_optim <- edit(optim)

这将打开的源代码optim使用R中的规定的编辑options ,然后就可以编辑和分配修正功能new_optim 。 我很喜欢这个功能非常多,查看代码或调试代码,例如,打印一些信息或变量,甚至将其分配给作进一步调查一个全局变量(当然你也可以使用debug )。

如果你只是想查看源代码,不希望打印您的控制台上恼人的长源代码,你可以使用

invisible(edit(optim))

显然,这不能用于查看C / C ++或Fortran源代码。

顺便说一句, edit可以打开其他对象像列表,矩阵,等,然后示出了具有属性的数据结构为好。 功能de可用于打开一个Excel等编辑(如果GUI支持的话)来修改矩阵或数据帧,并返回新的。 这是非常方便的时候,但是应该通常情况下是可以避免的,尤其是当你矩阵大。



Answer 7:

只要功能是写在纯的R不是C / C ++ / Fortran的,可以使用以下内容。 否则,最好的办法就是调试和使用“ 跳入 ”:

> functionBody(functionName)


Answer 8:

View([function_name]) -如。 View(mean)请务必使用大写[V]。 只读代码将在编辑器中打开。



Answer 9:

您也可以尝试使用print.function()这是S3通用,获得在控制台的功能写。



Answer 10:

在RStudio,有(至少)3种方式:

  1. 按F2键,光标在任何函数。
  2. 点击函数名,同时按住Ctrl或Command
  3. View (执行)(如上所述)

一个新的面板将源代码开放。 如果达到.Primitive或.C你需要另一种方法,对不起。



文章来源: How can I view the source code for a function?
标签: r function r-faq