6

这是来自 matplotlib 中 csv2rec 的源代码

如果它的唯一参数是'func,default',这个函数如何工作?

def with_default_value(func, default):
    def newfunc(name, val):
        if ismissing(name, val):
            return default
        else:
            return func(val)
    return newfunc

ismissing 接受一个名称和一个值,并确定该行是否应该在一个 numpy 数组中被屏蔽。

func 可以是 str、int、float 或 dateparser……它转换数据。也许并不重要。我只是想知道它如何获得“名称”和“价值”

我是初学者。感谢任何2美分!我希望能变得足够好来帮助别人!

4

4 回答 4

8

这个with_default_value函数通常(不准确地)被称为“闭包”(从技术上讲,闭包是返回的内部函数,这里newfunc- 参见例如这里)。更一般地说,with_default_value是一个高阶函数(“HOF”):它接受一个函数 ( func) 作为参数,它还返回一个函数 ( newfunc) 作为结果。

我已经看到答案将其与 Python 中的装饰器概念和构造混淆了,这绝对不是这种情况——尤其是因为您经常提到func它是内置的,例如int. 装饰器也是高阶函数,但更具体的是:返回装饰的,即“丰富的”,其函数参数的版本(它必须是唯一的参数——“带参数的装饰器”是通过一个更高级别的函数/闭包嵌套,而不是给装饰器 HOF 多个参数),它被重新分配为与该函数参数完全相同的名称(因此通常具有相同的签名 - 否则使用装饰器将非常奇特的、不习惯的、不可读的等)。

所以忘记与案例完全无关的装饰器,并专注于newfunc闭包。词法嵌套函数可以引用(尽管不能重新绑定)封闭函数的所有局部变量名称(包括参数名称,因为参数是局部变量)——这就是它被称为闭包的原因:它“封闭”这些“自由变量”。在这里,newfunc可以参考funcand default--does。

高阶函数在 Python 中是一件很自然的事情,特别是因为函数是一等对象(所以你不需要做任何特别的事情来将它们作为参数传递,将它们作为函数值返回,甚至将它们存储在列表或其他容器中等),并且函数和其他类型的对象之间没有命名空间的区别,没有仅仅因为提到它们就自动调用函数等等。(它更难 - 有点难,或者更难,取决于 - 在其他语言中确实吸引了很多这种区别)。在 Python 中,提及一个函数就是——提及;只有当函数对象(以名称或其他方式引用)后跟括号时,才会发生 CALL。

这就是这个例子的全部内容——如果您对其他一些具体方面仍有疑问,请随时编辑您的问题、在此处发表评论等!

编辑:所以 OP 礼貌地评论,要求提供更多“关闭工厂”的例子。这是一个 - 想象一些抽象的 GUI 工具包,你正在尝试做:

for i in range(len(buttons)):
  buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))

但这不起作用——ilambda后期绑定中,所以当一个按钮被点击i的时候,它的值总是最后一个按钮的索引,无论哪个被点击。有多种可行的解决方案,但关闭工厂是一种优雅的可能性:

def makeOnclick(message):
  return lambda: mainwin.settitle(message)

for i in range(len(buttons)):
  buttons[i].onclick(makeOnClick("button %d click!" % i))

在这里,我们使用闭包工厂来调整变量的绑定时间!-) 在一种或另一种特定形式中,这是闭包工厂的一个非常常见的用例。

于 2009-09-23T02:41:30.037 回答
6

这是一个 Python 装饰器——基本上是一个函数包装器。(阅读 PEP 318 中关于装饰器的所有内容——http: //www.python.org/dev/peps/pep-0318/

如果你看一下代码,你可能会发现这样的东西:

def some_func(name, val):
    # ...
some_func = with_default_value(some_func, 'the_default_value')

如果缺少 name 或 val 参数(假设它们设置为 None),此装饰器的意图似乎是提供默认值。

于 2009-09-23T01:55:59.913 回答
1

至于它为什么起作用:

with_default_value 返回一个函数对象,它基本上是该嵌套 newfunc 的副本,其中“func”调用和默认值替换为传递给 with_default_value 的任何内容。

如果有人执行 'foo = with_default_value(bar, 3)',则返回值基本上将是一个新函数:

def foo(name, val):
    ifismissing(name, val):
        return 3
    else:
        return bar(val)

这样您就可以获取该返回值并调用它。

于 2009-09-23T02:01:41.983 回答
0

这是一个返回另一个函数的函数。 namevalue是返回函数的参数。

于 2009-09-23T01:54:58.323 回答