这个python函数代码是如何工作的?
这来自matplotlib中csv2rec的源代码 如果该函数的唯一参数是“func,default”,那么该函数如何工作这个python函数代码是如何工作的?,python,function,matplotlib,Python,Function,Matplotlib,这来自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
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…它转换数据。也许不重要。我只是想知道它怎么能得到“名称”和“值”
我是初学者。谢谢你的礼物!我希望能变得足够好来帮助别人 这是一个返回另一个函数的函数
name
和value
是返回函数的参数。这是一个Python装饰器——基本上是一个函数包装器。(阅读PEP 318中关于装饰师的所有内容--)
如果您仔细查看代码,您可能会发现如下内容:
def some_func(name, val):
# ...
some_func = with_default_value(some_func, 'the_default_value')
如果缺少name或val参数(如果它们被设置为None,则可能是无),则此装饰器的意图似乎是提供一个默认值。关于它工作的原因:
with_default_值返回一个函数对象,它基本上是嵌套newfunc的一个副本,“func”调用和默认值用传递给with_default_值的任何内容替换
如果有人使用“foo=with_default_value(bar,3)”,则返回值基本上将是一个新函数:
def foo(name, val):
ifismissing(name, val):
return 3
else:
return bar(val)
因此,您可以获取该返回值,并调用它 这个带有默认值的
函数通常被称为(不精确地)闭包(从技术上讲,闭包是返回的内部函数,这里是newfunc
——参见示例)。更一般地说,带有默认值的是一个高阶函数(“HOF”):它将函数(func
)作为参数,还返回一个函数(newfunc
)作为结果
我看到一些答案将其与Python中的装饰器概念和构造相混淆,这肯定是而不是的情况——特别是因为您提到func
通常是一个内置函数,例如int
。decorator也是高阶函数,但非常特殊:返回其函数参数的修饰版本,即“丰富”版本的函数参数(必须是唯一的参数--“带参数的Decorators”是通过多层次的函数/闭包嵌套获得的,而不是通过给decorator提供多个参数),它被重新分配给与该函数参数完全相同的名称(因此通常具有相同的签名——否则使用decorator将是非常奇怪的、非惯用的、不可读的等等)
因此,忘记装饰器吧,它与案例完全无关,而关注newfunc
闭包。词汇嵌套函数可以引用(但不能重新绑定)封闭函数的所有局部变量名(包括参数名,因为参数是局部变量)——这就是它被称为闭包的原因:它“封闭”在这些“自由变量”之上。在这里,newfunc
可以引用func
和default
——并且确实如此
在Python中,高阶函数是非常自然的事情,特别是因为函数是一级对象(因此,无需做任何特殊的操作即可将其作为参数传递、作为函数值返回,甚至将其存储在列表或其他容器中等),函数和其他类型的对象之间没有名称空间上的区别,也没有仅仅因为提到了函数就自动调用函数,等等(在其他语言中,这一点比较难——有点难,或者更难,这取决于其他语言)。在Python中,提到一个函数就是——提到;只有当函数对象(以名称或其他方式引用)后面有括号时,才会发生调用
这就是这个例子的全部内容——如果您对其他一些具体方面还有疑问,请随意编辑您的问题,在这里发表评论,等等
编辑:因此,OP礼貌地发表评论,要求提供更多“关闭工厂”的例子。这里有一个——想象一下某种抽象的GUI工具包,您正在尝试:
for i in range(len(buttons)):
buttons[i].onclick(lambda: mainwin.settitle("button %d click!" % i))
但这并不正确--lambda
中的i
是延迟绑定的,因此在单击一个按钮时,i
的值总是最后一个按钮的索引,无论单击了哪个按钮。有各种可行的解决方案,但封闭工厂是一种极好的可能性:
def makeOnclick(message):
return lambda: mainwin.settitle(message)
for i in range(len(buttons)):
buttons[i].onclick(makeOnClick("button %d click!" % i))
在这里,我们使用闭包工厂来调整变量的绑定时间在某种特定的形式下,这是闭包工厂非常常见的用例。是否应该有一个类似“if ismissing”的空格?确切地说,除了新代码通常看起来更像:@with_default_value(some_func,'the_default_value')def some_func(name,val):#……我认为如果使用@语法(在函数定义之前),您必须有一个装饰器工厂(而这是一个纯除臭剂——2级深)。装饰器工厂可以接受参数,但不需要。除非在3中发生了更改。x@dcrosta我不这么认为。我一直在使用语法和装饰器互换,没有什么坏处。我猜我的立场是正确的。谢谢你的区分。这个HOF怎么会被调用呢?习语——就像大多数HOFs返回闭包一样,我只是认为它是实现函数工厂的一种简便方法。回答很好,那是一场战斗,首先我认为是另一个人完成的,然后你来接地!谢谢,我想我们都学到了一些东西!我想知道你是否还有其他类似的例子?只是好奇而已。不,w如果很难找到一个/做一个,那就很遗憾。