获取所有参数作为列表


79

R是否提供对象/函数/方法/关键字来获取所有函数参数?

用一个例子: function(a, b="default", ...)将提供ab以及...内部的功能环境。有没有一种说法类似list(...),这也将包括ab在结果?

或者换另一种方式:一个速记list(a=a, b=b, ...),给function(a, b, ...)


1
这个问题的问题是不清楚您要问什么。您是否在询问如何获取1)调用函数的;2)调用函数的表达式;3)函数定义中的默认值?您的问题根本不清楚,因此您针对这3个选项都得到了3种不同类型的答案。
TMS

Answers:


66

我认为您想要match.call

tmpfun <- function(a,b,...) {
print(as.list(match.call()))
print(as.list(match.call(expand.dots=FALSE)))
}
> tmpfun(a=1, b=2, c=3, d=4)
[[1]]
tmpfun

$a
[1] 1

$b
[1] 2

$c
[1] 3

$d
[1] 4

[[1]]
tmpfun

$a
[1] 1

$b
[1] 2

$...
$...$c
[1] 3

$...$d
[1] 4

23
如果未在函数调用中覆盖默认值,则此操作将失败。它不会列出具有默认设置但不会被覆盖的参数。

您是否知道导出此类功能的程序包(仅...作为参数)?
krlmlr

5
当tmpfun从另一个包装函数接收到参数时,此方法不起作用。(列表中只有未评估的参数)
RockScience 2015年

1
由于这些原因,可接受的答案应该是来自@ user399470的答案,该答案使用c(as.list(environment()), list(...))捕获默认args和提供的args的答案 。
洛伦兹·沃尔瑟特

76

一种解决方案是使用:

tempf <- function(a, b = 2, ...) {
    argg <- c(as.list(environment()), list(...))
    print(argg)
}
tempf(1, c = 3)
$a
[1] 1

$b
[1] 2

$c
[1] 3

这将创建参数值的命名列表。


您是否知道导出此类功能的程序包(仅...作为参数)?
krlmlr

2
或者,如果您没有...作为参数,则只需打印(as.list(environment()))
RockScience 2015年

3
这很好用,它比已接受的答案具有优势,它捕获传递给函数的,而不是可用于计算值的表达式。如果您试图保存args,以便以后可以调用该函数,则可能需要这些值。
肯·威廉姆斯

12

试试args功能

mean函数的参数是什么?

> args(mean)
function (x, ...) 
NULL

什么lm功能?

    > args(lm)
function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...) 
NULL

如果要获取参数列表,请尝试

as.list(args(lm))

不好的是,更多的函数无法与args调用(例如predict)配合使用。因此,骗子必须走到别处才能记住您要记住的一个参数/标志。
DChaps

8

在寻找相关内容时偶然发现了这个问题。虽然我认识到这已经有好几年了,但答复似乎并不令人满意,并且似乎没有针对该问题的现成解决方案。

可以使用formalsenvironment函数的组合进行(模糊)解决方法。下面的示例使用从形式库中提取的名称从环境中提取参数,然后附加省略号列表。如果希望具有在函数调用时设置的值,请​​将orig_values参数设置为TRUE。该函数仅包含在函数调用时隐式或显式设置的变量。

allargs <- function(orig_values = FALSE) {
  # get formals for parent function
  parent_formals <- formals(sys.function(sys.parent(n = 1)))

  # Get names of implied arguments
  fnames <- names(parent_formals)

  # Remove '...' from list of parameter names if it exists
  fnames <- fnames[-which(fnames == '...')]

  # Get currently set values for named variables in the parent frame
  args <- evalq(as.list(environment()), envir = parent.frame())

  # Get the list of variables defined in '...'
  args <- c(args[fnames], evalq(list(...), envir = parent.frame()))


  if(orig_values) {
    # get default values
    defargs <- as.list(parent_formals)
    defargs <- defargs[unlist(lapply(defargs, FUN = function(x) class(x) != "name"))]
    args[names(defargs)] <- defargs
    setargs <- evalq(as.list(match.call())[-1], envir = parent.frame())
    args[names(setargs)] <- setargs
  }
  return(args)
}


tempf <- function(a, b = 2, ...) {
  d <- 5
  b <- 3

  cat("Currently set values defined in call or formals\n")
  print(allargs())
  cat("Values as defined at the time of the call\n")
  print(allargs(T))
}

tempf(1, c = 3)

Currently set values defined in call or formals
$a
[1] 1

$b
[1] 3

$c
[1] 3

Values as defined at the time of the call
$a
[1] 1

$b
[1] 2

$c
[1] 3

6

我相信您正在寻找formals

formals(sd)
$x


$na.rm
[1] FALSE

dput以此为您提供您在问题中指定的表格:

dput(formals(sd))
list(x = , na.rm = FALSE)

请注意,这formals不适用于原始函数,仅适用于闭包。


2
这仅列出默认参数。
RockScience 2015年

1
test <- function(
  x = 1,
  y = 2,
  ...
) {
  if(length(list(...)) == 0) {
    print(as.list(environment()))
  } else {
    print(c(as.list(environment()), list(...)))
  }
}

test()
test(z = 3)

3
与已经提出的解决方案相比,使用这种方法有什么好处?特别是,这似乎与用户399470的答案极为相似
Matt Summersgill

1

rlang::fn_fmls 给出了一个简洁的解决方案:

library(ggplot2)
library(rlang)

# action
argument_list <- rlang::fn_fmls(fn = geom_point)

# evaluate output
class(argument_list)
#> [1] "pairlist"

is.list(argument_list)
#> [1] TRUE

argument_list
#> $mapping
#> NULL
#> 
#> $data
#> NULL
#> 
#> $stat
#> [1] "identity"
#> 
#> $position
#> [1] "identity"
#> 
#> $...
#> 
#> 
#> $na.rm
#> [1] FALSE
#> 
#> $show.legend
#> [1] NA
#> 
#> $inherit.aes
#> [1] TRUE

reprex软件包(v0.3.0)创建于2020-02-25

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.