functools.partial与普通Python函数
我正在学习关于部分函数(partials)以及何时使用它们。在这篇关于 部分函数与匿名函数(lambdas) 的页面中,接受的回答解释了部分函数相对于匿名函数的一个优点,就是部分函数有一些有用的属性,可以帮助我们更好地理解它们的结构和功能。因此,我们可以对部分函数做以下操作:
import functools
f = functools.partial(int, base=2)
print f.args, f.func, f.keywords
((), int, {'base': 2})
实际上,我们不能对匿名函数做这样的操作:
h = lambda x : int(x,base=2)
print h.args, h.func, h.keywords
AttributeError: 'function' object has no attribute 'args'
但实际上,我们也不能对“普通的”Python函数这样做:
def g(x) :
return int(x,base=2)
print g.args, g.func, g.keywords
AttributeError: 'function' object has no attribute 'args'
那么,为什么部分函数的功能比普通的Python函数更多呢?这种设计的意图是什么?难道普通函数的自我检查功能就被认为是没用的吗?
1 个回答
6
函数确实知道自己能接受哪些参数。函数的属性名称和数据结构主要是为了让解释器使用,而不是为了开发者,但这些信息是存在的。你需要查看 .func_defaults
和 .func_code.co_varnames
这些结构(还有其他一些)才能找到这些细节。
使用 inspect.getargspec()
函数 可以更简单地提取这些信息:
>>> import inspect
>>> h = lambda x : int(x,base=2)
>>> inspect.getargspec(h)
ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
需要注意的是,lambda
表达式产生的对象类型和 def funcname():
定义的函数是完全一样的。
不过,这并不能告诉你会传入 被包装的函数 的具体参数。这是因为函数的用途比较广泛,而 functools.partial()
是专门的,因此可以很容易地提供这些信息。因此,partial
会告诉你 base=2
会被传入 int()
,但 lambda
只能告诉你它 接收 了一个参数 x
。
所以,虽然 functools.partial()
对象可以告诉你哪些参数会传入哪个函数,但 function
对象只能告诉你它接收了哪些参数,因为调用被包装函数的工作是由构成函数 主体 的(可能更复杂的)表达式来完成的。而且这还忽略了那些根本不调用其他函数的函数。