functools:partial 与 reduce
使用 partial 创建专用函数,并使用 reduce 折叠序列。
functools:partial 与 reduce 是 CoddyKit 上的免费 Python Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
functools 概览
functools 是标准库模块,包含可操作其他函数或返回其他函数的高阶函数。
import functools
# partial, reduce, lru_cache, wraps, cached_property ...
print(dir(functools))partial()
functools.partial(func, *args, **kw) 会创建一个新的可调用对象,并预先填充部分参数。
import functools
def power(base, exp):
return base ** exp
square = functools.partial(power, exp=2)
cube = functools.partial(power, exp=3)
print(square(4)) # 16
print(cube(3)) # 27将 partial 用于方法
使用 partial 为方法固定参数,使其可以用作回调函数或事件处理程序。
import functools, logging
logger = logging.getLogger("app")
log_error = functools.partial(logger.log, logging.ERROR)
log_error("Something went wrong")partial 与 lambda 的比较
与 lambda 相比,partial 更适合预先填充参数,因为它支持序列化,具有良好的 repr,并且能够保留文档字符串。
import functools
mul = lambda x, y: x * y
double_lambda = lambda x: mul(x, 2) # lambda approach
double_partial = functools.partial(mul, y=2) # partial approach
print(double_partial(5)) # 10reduce()
functools.reduce(func, iterable, initial) 使用二元函数从左到右折叠可迭代对象。
import functools, operator
total = functools.reduce(operator.add, [1,2,3,4,5])
print(total) # 15
product = functools.reduce(operator.mul, [1,2,3,4,5], 1)
print(product) # 120使用 reduce 构建 max()
通过重新实现 max() 来演示 reduce:
import functools
def my_max(seq):
return functools.reduce(lambda a, b: a if a > b else b, seq)
print(my_max([3, 1, 4, 1, 5, 9])) # 9扁平化嵌套列表
将 reduce 与 operator.iconcat 结合使用,可以扁平化一层嵌套。
import functools, operator
nested = [[1,2],[3,4],[5]]
flat = functools.reduce(operator.iconcat, nested, [])
print(flat) # [1, 2, 3, 4, 5]使用 partial 构建 URL
partial 的一个实用模式是固定基础 URL,并创建专用的请求辅助函数。
import functools, urllib.request
def fetch(base, path):
url = base.rstrip("/") + "/" + path.lstrip("/")
with urllib.request.urlopen(url) as r:
return r.read()
github = functools.partial(fetch, "https://api.github.com")
# github("/users/octocat")wraps():保留元数据
编写装饰器时,请使用 @functools.wraps(wrapped),使包装器保留原函数的名称和文档字符串。
import functools
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
return func(*args, **kw)
return wrapper
@decorator
def greet(name):
"""Say hello."""
return f"Hello, {name}"
print(greet.__name__) # greet
print(greet.__doc__) # Say hello.total_ordering
@functools.total_ordering 会在您定义 __eq__ 和 __lt__/__le__/__gt__/__ge__ 中任意一个方法后,补齐缺少的比较方法。
import functools
@functools.total_ordering
class Version:
def __init__(self, major, minor):
self.v = (major, minor)
def __eq__(self, o): return self.v == o.v
def __lt__(self, o): return self.v < o.v
print(Version(1,2) >= Version(1,1)) # Truesingledispatch
@functools.singledispatch 会创建一个函数,根据第一个参数的类型分派到不同的实现。
import functools
@functools.singledispatch
def process(arg):
raise NotImplementedError(type(arg))
@process.register(int)
def _(n): return n * 2
@process.register(str)
def _(s): return s.upper()
print(process(5)) # 10
print(process("hi")) # HI快速检查
functools.partial(pow, 2) 会创建什么?
复习
partial 会预先填充函数参数;reduce 使用二元函数折叠序列;wraps 保留装饰器元数据;total_ordering 补齐比较方法;singledispatch 根据类型进行分派。
常见问题解答
「functools:partial 与 reduce」课时是免费的吗?
是的 — 「functools:partial 与 reduce」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「functools:partial 与 reduce」这节课中我会学到什么?
使用 partial 创建专用函数,并使用 reduce 折叠序列。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「functools:partial 与 reduce」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- itertools:无限与有限迭代器
- itertools:组合数学
- functools:partial 与 reduce
- functools:lru_cache 与 cached_property