【问题标题】:Modify an argument of a function that is inside another function, without having to redefine the whole function again修改另一个函数内部的函数的参数,而不必再次重新定义整个函数
【发布时间】:2020-10-17 02:08:13
【问题描述】:

编辑:

labelFormat 函数来自 leaflet 包。
我想修改 format 函数内的一个参数,该函数位于 formatNum 函数内。

所以从这里开始:

labelFormat <- function (prefix = "", suffix = "", between = " &ndash; ", digits = 3, 
    big.mark = ",", transform = identity) 
{
    formatNum <- function(x) {
        format(round(transform(x), digits), trim = TRUE, scientific = FALSE, 
            big.mark = big.mark)
    }
    function(type, ...) {
        switch(type, numeric = (function(cuts) {
            paste0(prefix, formatNum(cuts), suffix)
        })(...), bin = (function(cuts) {
            n <- length(cuts)
            paste0(prefix, formatNum(cuts[-n]), between, formatNum(cuts[-1]), 
                suffix)
        })(...), quantile = (function(cuts, p) {
            n <- length(cuts)
            p <- paste0(round(p * 100), "%")
            cuts <- paste0(formatNum(cuts[-n]), between, formatNum(cuts[-1]))
            paste0("<span title=\"", cuts, "\">", prefix, p[-n], 
                between, p[-1], suffix, "</span>")
        })(...), factor = (function(cuts) {
            paste0(prefix, as.character(transform(cuts)), suffix)
        })(...))
    }
}

我想要这个:

labelFormat <- function (prefix = "", suffix = "", between = " &ndash; ", digits = 3, 
    big.mark = ",", transform = identity) 
{
    formatNum <- function(x) {
        format(round(transform(x), digits), trim = TRUE, scientific = FALSE, 
            big.mark = big.mark, decimal.mark = ',')
    }
    function(type, ...) {
        switch(type, numeric = (function(cuts) {
            paste0(prefix, formatNum(cuts), suffix)
        })(...), bin = (function(cuts) {
            n <- length(cuts)
            paste0(prefix, formatNum(cuts[-n]), between, formatNum(cuts[-1]), 
                suffix)
        })(...), quantile = (function(cuts, p) {
            n <- length(cuts)
            p <- paste0(round(p * 100), "%")
            cuts <- paste0(formatNum(cuts[-n]), between, formatNum(cuts[-1]))
            paste0("<span title=\"", cuts, "\">", prefix, p[-n], 
                between, p[-1], suffix, "</span>")
        })(...), factor = (function(cuts) {
            paste0(prefix, as.character(transform(cuts)), suffix)
        })(...))
    }
}

查看format 函数中的新参数decimal.mark。
但要做到这一点,我不想重新定义 labelFormat 函数。

在 Python 中,我使用非常相似的东西来修改函数内的参数。假设我们要修改json.dumps的默认行为:

import functools
import json

my_json_dumps = functools.partial(json.dumps, ensure_ascii=False)

现在我可以调用my_json_dumps而不是使用json.dumps,这样我就不需要重新定义整个函数了。

我的问题有点不同,因为我需要修改内部函数内部的参数!

【问题讨论】:

  • 函数中的变量在全局环境中不可用。最好不要在另一个函数中定义函数。只需在另一个之前创建它并在第二个中使用它。
  • 函数g仅在f运行时创建。 (并且每次f 在不同的环境下运行时都会重新创建,因此每次都会得到一个“不同的”f。)如果从f 返回的值没有包含g 的值,调用函数f 后将不存在。鉴于您所要求的内容没有多大意义,您能否更详细地描述您要解决的具体问题?
  • 如果您能够修改它,您可以使用&lt;&lt;- 赋值将g() 函数分配给一个全局变量。
  • 如果您提供更多背景信息肯定会很有用 - 即这是一个实际问题,还是“我只是想知道如何......?”问题?
  • 我添加了更多上下文,我认为现在最好重命名答案的标题...谢谢。

标签: r function


【解决方案1】:

在这种情况下,labelFormat 返回一个函数,该函数包含对定义 formatNum 的环境的引用。在这里我们可以创建一个包装器来更改该值

my_labelFormat <- function(...) {
   fun <- labelFormat(...)
   evalq(formatNum <- function(x) {
     format(round(transform(x), digits), trim = TRUE, scientific = FALSE, 
            big.mark = big.mark, decimal.mark = ',')
  }, environment(fun))
  return(fun)
}

所以我们调用了默认的labelFormat 函数,但他们操纵环境来改变formatNum 函数

【讨论】:

    【解决方案2】:

    这并不容易。我无法从f() 外部调用g(),因为在调用f() 并执行第一步之前,该函数不存在。要查看此内容,请尝试以下操作:

    debug(f)
    f(1)
    ls() ## shows 'number', the only object in the local environment
    g()  ## Error: could not find function g
    <ENTER>
    <ENTER>
    g()  ## prints 'Hi', because the function has now been defined
    

    获得g() 的定义的一个超级俗气的方法是:

    eval(body(f)[[2]])
    g()
    ## "Hi"
    

    这会从定义函数的表达式(恰好是g() 的定义)中挑选出第二个元素,并在当前环境中对其进行评估。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-10
      • 2021-10-10
      相关资源
      最近更新 更多