gpt4 book ai didi

r - 如何查看函数的源代码?

转载 作者:行者123 更新时间:2023-12-03 03:54:40 25 4
gpt4 key购买 nike

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

> 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 .我怎样才能找到这些的源代码?

最佳答案

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 的未导出函数命名空间。您可以使用 ::: 查看未导出函数的源代码。运算符(operator)或 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在编译代码中调用入口点,因此如果您想完全理解该函数,则必须查看编译代码的来源。 This R 源代码的 GitHub 镜像是一个不错的起点。函数 pryr::show_c_source可以是一个有用的工具,因为它会将您直接带到 .Internal 的 GitHub 页面。和 .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 包中,因此您可以输入 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])

或者,如果包开发是公开托管的(例如通过 GitHubR-ForgeRForge.net ),您可能可以在线浏览源代码。

基础包中的编译代码

某些包被视为“基础”包。这些软件包随 R 一起提供,并且它们的版本被锁定为 R 的版本。示例包括 base , compiler , stats , 和 utils .因此,如上所述,它们不能作为单独的可下载包在 CRAN 上使用。相反,它们是 /src/library/ 下各个包目录中 R 源代码树的一部分。 .下一节将介绍如何访问 R 源。

R 解释器中内置的编译代码

如果要查看 R 解释器内置的代码,则需要下载/解压 R 源代码;或者您可以通过 R Subversion repository 在线查看资源或 Winston Chang's github mirror .

Uwe Ligges R news article (PDF) (第 43 页)是关于如何查看 .Internal 的源代码的很好的一般引用。和 .Primitive功能。基本步骤是先在 src/main/names.c中查找函数名然后在 src/main/*中的文件中搜索“C-entry”名称.

关于r - 如何查看函数的源代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19226816/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com