在 Python 中,函数是一等对象。那什么是“一等对象”呢?“一等对象”的定义如下:
能接受函数为参数,或者把函数作为结果返回的函数是高阶函数(higher-order function).
lambda 关键字在 Python 表达式内创建匿名函数。
>>> fruits = ['strawberry', 'fig', 'apple', 'cherry', 'raspberry', 'banana']
>>> sorted(fruits, key=lambda word: word[::-1])
['banana', 'apple', 'fig', 'raspberry', 'strawberry', 'cherry']
只要实现对象的 __call__
方法,该对象就可以表现得像函数。
class MyDemo:
def __call__(self):
return "hello world"
a = MyDemo()
print(a())
imspect
模块来提取函数签名def clip(text, max_len=80):
"""在max_len前面或后面的第一个空格处截断文本 """
end = None
if len(text) > max_len:
space_before = text.rfind(' ', 0, max_len)
if space_before >= 0:
end = space_before
else:
space_after = text.rfind(' ', max_len)
if space_after >= 0:
end = space_after
if end is None: # 没找到空格
end = len(text)
return text[:end].rstrip()
from inspect import signature
sig = signature(clip)
print(sig)
print(str(sig))
for name, param in sig.parameters.items():
print(param.kind, ':', name, '=', param.default)
"""
output:
(text, max_len=80)
(text, max_len=80)
POSITIONAL_OR_KEYWORD : text =
POSITIONAL_OR_KEYWORD : max_len = 80
"""
inspect.signature
函数返回一个 inspect.Signature
对象,它有一个 parameters
属性,这是一个有序映射,把参数名和inspect.Parameter
对象对应起来。各个 Parameter
属性也有自己的属性,例如 name
, default
和 kind
。特殊的inspect._empty
值表示没有默认值,考虑到 None
是有效的默认值,这么做是合理的。
kind
属性的值是 _ParameterKind
类中的5个值之一,例举如下。
POSITIONAL_OR_KEYWORD
VAR_POSITIONAL
VAR_KEYWORD
KEYWORD_ONLY
POSITIONAL_ONLY
inspect.Signature
对象有个 bind
方法,它可以把任意个参数绑定到签名中的形参上,所用的规则与实参到形参的匹配方式一样。框架可以使用这个方法在真正调用函数前验证参数。
def clip(text, max_len=80):
"""在max_len前面或后面的第一个空格处截断文本 """
end = None
if len(text) > max_len:
space_before = text.rfind(' ', 0, max_len)
if space_before >= 0:
end = space_before
else:
space_after = text.rfind(' ', max_len)
if space_after >= 0:
end = space_after
if end is None: # 没找到空格
end = len(text)
return text[:end].rstrip()
from inspect import signature
sig = signature(clip)
my_params = {
'text': "abcd df", 'max_len': 3}
bound_args = sig.bind(**my_params)
print(bound_args)
for name, value in bound_args.arguments.items():
print(name, "=", value)
del my_params['text']
bound_args = sig.bind(**my_params)
"""
output:
text = abcd df
max_len = 3
Traceback (most recent call last):
File "E:/code/python/py_study/test.py", line 28, in
bound_args = sig.bind(**my_params)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\inspect.py", line 3015, in bind
return args[0]._bind(args[1:], kwargs)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\inspect.py", line 2930, in _bind
raise TypeError(msg) from None
TypeError: missing a required argument: 'text'
text = abcd df
max_len = 3
"""
functools.partial
冻结参数functools.partial
这个高阶函数用于部分应用一个函数。部分应用是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。使用这个函数可以把接受一个或多个参数的函数改编成需要回调的API,这样参数更少。
>>> from operator import mul
>>> from functools import partial
>>> triple = partial(mul, 3)
>>> triple(7)
21
>>> list(map(triple, range(1, 10)))
[3, 6, 9, 12, 15, 18, 21, 24, 27]
又写完一章啦,真希望快点结束这个专题。下一章我们将介绍如何使用一等函数实现设计模式