这个Python函数代码如何工作?
这是来自 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 美分!我希望自己能变得足够好,帮助别人!
this is from the source code of csv2rec in matplotlib
how can this function work, if its only parameters are '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 takes a name and a value and determines if the row should be masked in a numpy array.
func will either be str, int, float, or dateparser...it converts data. Maybe not important. I'm just wondering how it can get a 'name' and a 'value'
I'm a beginner. Thanks for any 2cents! I hope to get good enough to help others!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这个
with_default_value
函数通常被(不准确地)称为“闭包”(从技术上讲,闭包实际上是返回的内部函数,这里newfunc< /code>——参见此处)。更一般地说,
with_default_value
是一个高阶函数(“HOF”):它接受一个函数 (func
) 作为参数,它还返回一个函数 (newfunc
) 作为结果。我看到一些答案将其与 Python 中的装饰器概念和构造混淆了,这绝对不是这种情况——特别是因为你提到了 func通常是内置函数,例如
int
。装饰器也是高阶函数,但是是特定的函数:返回其函数参数的装饰(即“丰富”)版本(必须是唯一参数 - “带参数的装饰器”通过多一层函数/闭包嵌套获得,不是通过为装饰器 HOF 提供多个参数),它被重新分配为与该函数参数完全相同的名称(因此通常具有相同的名称)签名——否则使用装饰器将是极其特殊、不惯用、不可读等)。因此,忘记装饰器,它与案例完全无关,而专注于 newfunc 闭包。词法嵌套函数可以引用(尽管不能重新绑定)封闭函数的所有局部变量名称(包括参数名称,因为参数是局部变量)——这就是它被称为闭包的原因:它“封闭”这些函数“自由变量”。在这里,
newfunc
可以引用func
和default
——并且确实如此。高阶函数在 Python 中是很自然的事情,特别是因为函数是一等对象(因此您无需执行任何特殊操作即可将它们作为参数传递、将它们作为函数值返回,甚至将它们存储在列表或其他容器中等),并且函数和其他类型的对象之间没有命名空间区别,不会仅仅因为提到它们就自动调用函数,等等(这更难 - 有点难,或者更难,取决于 - 在其他语言中确实有很多这样的区别)。在 Python 中,提及函数只是——提及;仅当函数对象(通过名称或其他方式引用)后跟括号时,才会发生 CALL。
这就是这个例子的全部内容——如果您对其他一些具体方面仍有疑问,请随时编辑您的问题、在此处发表评论等!
编辑:因此OP礼貌地发表评论,要求提供更多“关闭工厂”的例子。这是一个 - 想象某种抽象的 GUI 工具包,你正在尝试这样做:
但这不起作用 -
lambda
中的i
迟到了 -绑定,因此当单击一个按钮时,i
的值始终将是last 按钮的索引,无论单击的是哪一个按钮。有各种可行的解决方案,但闭包工厂是一种优雅的可能性:在这里,我们使用闭包工厂来调整变量的绑定时间!-)在一种特定形式或另一种形式中,这是闭包工厂的一个非常常见的用例。
This
with_default_value
function is what's often referred to (imprecisely) as "a closure" (technically, the closure is rather the inner function that gets returned, herenewfunc
-- see e.g. here). More generically,with_default_value
is a higher-order function ("HOF"): it takes a function (func
) as an argument, it also returns a function (newfunc
) as the result.I've seen answers confusing this with the decorator concept and construct in Python, which is definitely not the case -- especially since you mention
func
as often being a built-in such asint
. Decorators are also higher-order functions, but rather specific ones: ones which return a decorated, i.e. "enriched", version of their function argument (which must be the only argument -- "decorators with arguments" are obtained through one more level of function/closure nesting, not by giving the decorator HOF more than one argument), which gets reassigned to exactly the same name as that function argument (and so typically has the same signature -- using a decorator otherwise would be extremely peculiar, un-idiomatic, unreadable, etc).So forget decorators, which have absolutely nothing to do with the case, and focus on the
newfunc
closure. A lexically nested function can refer to (though not rebind) all local variable names (including argument names, since arguments are local variables) of the enclosing function(s) -- that's why it's known as a closure: it's "closed over" these "free variables". Here,newfunc
can refer tofunc
anddefault
-- and does.Higher-order functions are a very natural thing in Python, especially since functions are first-class objects (so there's nothing special you need to do to pass them as arguments, return them as function values, or even storing them in lists or other containers, etc), and there's no namespace distinction between functions and other kinds of objects, no automatic calling of functions just because they're mentioned, etc, etc. (It's harder - a bit harder, or MUCH harder, depending - in other languages that do draw lots of distinctions of this sort). In Python, mentioning a function is just that -- a mention; the CALL only happens if and when the function object (referred to by name, or otherwise) is followed by parentheses.
That's about all there is to this example -- please do feel free to edit your question, comment here, etc, if there's some other specific aspect that you remain in doubt about!
Edit: so the OP commented courteously asking for more examples of "closure factories". Here's one -- imagine some abstract kind of GUI toolkit, and you're trying to do:
but this doesn't work right --
i
within thelambda
is late-bound, so by the time one button is clickedi
's value is always going to be the index of the last button, no matter which one was clicked. There are various feasible solutions, but a closure factory's an elegant possibility:Here, we're using the closure factory to tweak the binding time of variables!-) In one specific form or another, this is a pretty common use case for closure factories.
这是一个 Python 装饰器——基本上是一个函数包装器。 (阅读 PEP 318 中有关装饰器的所有内容 -- http://www.python.org /dev/peps/pep-0318/)
如果你查看代码,你可能会发现类似这样的东西:
如果 name 或 val 参数丢失,这个装饰器的意图似乎是提供一个默认值(据推测,如果它们设置为“无”)。
This is a Python decorator -- basically a function wrapper. (Read all about decorators in PEP 318 -- http://www.python.org/dev/peps/pep-0318/)
If you look through the code, you will probably find something like this:
The intention of this decorator seems to supply a default value if either the name or val arguments are missing (presumably, if they are set to None).
至于它的工作原理:
with_default_value 返回一个函数对象,它基本上是嵌套 newfunc 的副本,其中“func”调用和默认值替换为传递给 with_default_value 的任何内容。
如果有人执行“foo = with_default_value(bar, 3)”,则返回值基本上将是一个新函数:
因此您可以获取该返回值并调用它。
As for why it works:
with_default_value returns a function object, which is basically going to be a copy of that nested newfunc, with the 'func' call and default value substited with whatever was passed to with_default_value.
If someone does 'foo = with_default_value(bar, 3)', the return value is basically going to be a new function:
so you can then take that return value, and call it.
这是一个返回另一个函数的函数。
name
和value
是返回函数的参数。This is a function that returns another function.
name
andvalue
are the parameters of the returned function.