当前位置: 首页 > 知识库问答 >
问题:

如何查看函数的源代码?

谭泳
2023-03-14

我想看看一个函数的源代码,看看它是如何工作的。我知道我可以通过在提示符下键入函数名称来打印函数:

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

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

> 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.
> 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")

如何找到.primitial函数的功能?类似地,某些函数调用.c.call.fortran.external.internal。我怎样才能找到这些的源代码?

共有1个答案

陶元凯
2023-03-14

useMethod(“t”)告诉您t()是一个(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

“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系统是一种较新的方法调度系统,是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.makenamestsstats命名空间中未导出的函数。可以使用:::运算符或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>

调用.c.call.fortran.external.internal.primitial的函数是已编译代码中的调用入口点,因此如果要完全理解该函数,必须查看已编译代码的源代码。这个R源代码的GitHub镜像是一个不错的起点。函数pryr::show_c_source可以是一个有用的工具,因为它可以将您直接带到GitHub页面进行.internal.primitial调用。包可以使用.c.call.fortran.external;而不是.internal.primitial,因为它们用于调用内置在R解释器中的函数。

对上述某些函数的调用可能使用一个对象而不是字符串来引用已编译的函数。在这些情况下,对象的类为“nativesymbolinfo”“registerednativesymbol”“nativesymbol”;并且打印对象会产生有用的信息。例如,optim调用.external2(C_optimhess,res$par,fn1,gr1,con)(注意,这是C_optimhess,而不是“C_optimhess”)。optim在stats包中,因此您可以键入stats:::C_optimhess查看有关被调用的已编译函数的信息。

如果要查看包中的已编译代码,将需要下载/解包包源。安装的二进制文件不足。包的源代码可以从包最初安装的同一个CRAN(或CRAN兼容)存储库中获得。download.packages()函数可以为您获取包源。

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

这将下载Matrix包的源版本,并将相应的.tar.gz文件保存在当前目录中。已编译函数的源代码可以在未压缩和未处理文件的src目录中找到。解压和解压步骤可以在r外部完成,也可以在r内部使用untar()函数完成。可以将下载和扩展步骤合并到单个调用中(注意,一次只能下载一个包并以这种方式解包):

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

或者,如果包html" target="_blank">开发是公开托管的(例如通过GitHub、R-Forge或RForge.net),您可能可以在线浏览源代码。

Uwe Ligges的R news文章(PDF)(第43页)是如何查看.internal.primitial函数源代码的一个很好的通用参考。基本步骤是首先在src/main/names.c中查找函数名,然后在src/main/*中的文件中搜索“C-entry”名称。

 类似资料:
  • 根据文档,是中的一个多态函数,根据作为第一个参数传递的内容,实际上会调用不同的函数。 但是,文档没有给出实际为任何特定类调用的函数名称的任何信息。 如果我想查看在类型的对象上调用函数时的源代码,那么最简单的方法是什么?

  • 问题内容: 使用Eclipse,我想查看核心Java类(Eg )的源代码,但是当我使用“打开声明”导航到源代码时,它显示“未找到源代码”,并提供了附加源代码的选项。 我的问题是;我如何附加来源?我从哪里获得库的源.jar ? 问题答案: 您需要安装JDK。那你可以看看 对我来说(取决于您当前的版本) 您无需获取特殊的开源版本。

  • 问题内容: 是否有任何的方式来查看Java中的默认类背后的实际代码(,,等),看看 究竟 它是什么,是怎么回事? 我不仅指文档或方法列表等,还包括源代码本身的详细信息(换句话说,如果将其复制并粘贴到整个方法/类中,则可以用来创建整个方法/类的精确副本) Java程序的代码)。 问题答案: JDK安装程序在名为的文件中提供了所有API类的Java源代码。它通常只是坐在您的安装目录中。解压缩,看看。

  • 我点击 build.gradle里 dependencies 块中的 { implementation } IDEA跳转到: 我点击 build.gradle 里的关键字 dependencies { IDEA跳转到: 这2个文件只有接口,都不是实现源码,可我的gradleHome是all 版本的,不是bin 版本的,怎么还看不到源码呢 ?

  • 问题内容: 假设我有如下定义的Python函数: 我可以使用获取函数的名称。如上所述,我如何以编程方式获取其源代码? 问题答案: 如果该功能来自文件系统上可用的源文件,则可能会有帮助: 如果foo定义为: 然后: 返回值: 但是我相信,如果函数是从字符串,流中编译的,或者是从编译文件中导入的,那么您将无法检索其源代码。

  • 问题内容: 有没有办法查看内置函数如何在python中工作?我不仅意味着如何使用它们,而且还意味着它们是如何构建的,排序或枚举等背后的代码是什么? 问题答案: 由于Python是开源的,因此你可以阅读源代码。 要找出实现了特定模块或功能的文件,通常可以打印属性。或者,你可以使用该inspect模块,请参阅的文档中的“ 检索源代码 ”部分。 对于内置的类和方法,这是不是这样,因为直白,并会返回一个类