Functools -- partial
partial 是 Python 函数式编程的核心工具之一:
from functools import partial
它的作用是:
预先为一个函数绑定部分参数,返回一个新的函数。
这叫 偏函数(partial function)。
from functools import partial
def power(base, exponent):
return base ** exponent
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(5)) # 125
- square、cube 都是 partial 生成的新函数。
- 它们已经绑定好了 exponent 参数。
⭐ 作用总结
- 给函数预填默认参数
- 函数定制化
- 方便函数作为回调传递
- 用于 map/filter/reduce 更优雅
- 用于 asyncio / thread pool 更方便
- 让代码更短、更可读
import requests
from functools import partial
get_json = partial(requests.get, headers={
"User-Agent": "Mozilla/5.0"
})
resp = get_json("https://api.example.com/data")
print(resp.json())
以后不需要每次都写 headers。
from functools import partial
from loguru import logger
info = partial(logger.log, "INFO")
debug = partial(logger.log, "DEBUG")
info("程序开始")
debug("变量 x=10")
open_utf8 = partial(open, encoding="utf-8")
with open_utf8("text.txt") as f:
print(f.read())
比每次写 open(..., encoding="utf-8") 更优雅。
def multiply(a, b):
return a * b
double = partial(multiply, 2)
print(list(map(double, [1, 2, 3])))
输出:
[2, 4, 6]
button_click = partial(on_click, id=123)
GUI 事件回调只能放一个函数参数,partial 很好用。
from concurrent.futures import ThreadPoolExecutor
from functools import partial
def download(url, folder):
...
download_to_tmp = partial(download, folder="/tmp")
with ThreadPoolExecutor() as p:
p.map(download_to_tmp, urls)
避免 lambda,代码更清晰。
partial(func, *args, **kwargs)
关键点:
- args 会填到左边的参数
- kwargs 会填到函数对应的关键字参数
- 剩余参数仍可传入
示例:
def test(a, b, c):
print(a, b, c)
f = partial(test, 1, c=3)
f(2) # a=1, b=2, c=3
f = partial(pow, exponent=2)
f.__name__ = "square"
| 功能 | partial | lambda | | 可读性 | ⭐⭐⭐⭐⭐ | ⭐⭐ | | 性能 | ⭐⭐⭐⭐ | ⭐⭐⭐ | | 可调试性 | ⭐⭐⭐⭐⭐ | ⭐ | | 代码简洁 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | | 支持绑定参数 | ✅ | ✅ | | 支持绑定关键字参数 | ✅ | ✅ | | 适合回调 | ✅ | ⚠️ 一般 |
partial 推荐优先使用。
from functools import partial
basetwo = partial(int, base=2)
print(basetwo('10010')) # 18
def func(a, b, c):
print(a, b, c)
f = partial(func, 1, b=2)
f(c=3) # OK
如果传入重复参数:
f(b=5) # ❌ TypeError
因为 b 已经在 partial 中绑定过了。
from functools import partial
partial(func, *args, **kwargs)
用途:
- 函数预绑定参数
- 让函数变简单
- GUI、回调、线程池
- requests、open、logger 封装
优势:
- 可读性更高优于 lambda
- 参数依然可扩展
- 适配旧代码和回调