什么是python中的functools.partial

它是什么?

functools.partial 用来预先绑定一个可调用对象(函数/类/方法等)的部分位置参数和关键字参数,返回一个新的可调用对象。调用新对象时,只需再提供剩余参数。

from functools import partial

def connect(host, port, timeout):
    ...
# 预配置 timeout,得到一个“半成品”函数
fast_connect = partial(connect, timeout=1.0)
fast_connect("127.0.0.1", 6379)   # 等价 connect("127.0.0.1", 6379, timeout=1.0)

核心理解:把“总是一样的那部分参数”提前固定,得到一个语义更清晰、调用更简短的函数。

基本用法

from functools import partial

def power(x, n): return x ** n

square = partial(power, n=2)  # 固定 n
cube   = partial(power, n=3)

print(square(5))  # 25
print(cube(2))    # 8

	•	既可绑定位置参数也可绑定关键字参数;混用没问题。
	•	如果调用时又传了同名关键字,会报错:TypeError: multiple values for argument ...

典型场景

1)做回调/适配“签名不匹配”的接口

GUI/异步库经常要求回调只有一个参数;用 partial 填好其它上下文:

def on_click(user_id, event): ...
cb = partial(on_click, user_id="u123")
button.set_callback(cb)  # 框架只把 event 传给 cb

2)给并行/流水线“注入常量参数”

from concurrent.futures import ThreadPoolExecutor
from functools import partial

def download(url, timeout):
    ...

dl = partial(download, timeout=5)
with ThreadPoolExecutor() as ex:
    list(ex.map(dl, urls))   # 只喂 url,timeout 已固定

3)配置 key/predicate 等“行为型参数”

from functools import partial

def score(path, weights): ...
ranker = partial(score, weights={"size": 0.3, "mtime": 0.7})
files_sorted = sorted(files, key=ranker)

4)当“函数工厂”的轻量替代(比闭包更简洁)

def add(x, y): return x + y

add5 = partial(add, 5)   # 类似 make_adder(5)
print(add5(10))          # 15

partial 在 C 层实现,通常比等价的 lambda/闭包更快且更简洁。

与方法的细节(partialmethod)

对实例方法提前绑定额外参数,推荐用 functools.partialmethod 在类定义里写得更优雅:

from functools import partialmethod

class Logger:
    def log(self, level, msg):
        print(f"[{level}] {msg}")

    info  = partialmethod(log, "INFO")   # self 会在调用时自动绑定
    error = partialmethod(log, "ERROR")

L = Logger()
L.info("boot ok")    # 等价于 L.log("INFO", "boot ok")

partial 也能和方法配合,但涉及描述符绑定细节,类里定义别名方法时优先用 partialmethod。

可检查属性 & 调试

partial 返回的对象有三个只读属性,便于调试/反射:
	•	.func:原始可调用对象
	•	.args:已绑定的位置参数(tuple)
	•	.keywords:已绑定的关键字参数(dict 或 None)

p = partial(pow, 2, exp=5)
print(p.func, p.args, p.keywords)  # <built-in function pow> (2,) {'exp': 5}

inspect.signature(p) 能看到剩余参数签名(对 IDE 友好)。

与 lambda/闭包怎么选?
• 只是预填参数 → partial 更简洁、往往更快。
• 需要在调用前改写参数/增加逻辑(比如校验、分支) → lambda/闭包/装饰器。

# 只预填参数:partial 更合适
square = partial(pow, exp=2)

# 预填 + 额外逻辑:闭包/装饰器更合适
def safe_pow(exp):
    def f(x):
        if x < 0: return None
        return pow(x, exp)
    return f

小坑与建议
1. 重复赋值冲突:同一参数既在 partial 里绑定、又在调用时传入,会报错(这是好事,能尽早暴露错误)。
2. 绑定的是“对象引用”:若绑定的是可变对象(dict/list),后续修改该对象会影响调用结果(与 Python 一贯语义一致)。
3. 签名变动:原函数参数签名调整后,相关 partial 也要更新(否则运行期报错)。
4. 日志/名称:partial 对象没有 name;日志里可用 p.func.name 或显式命名变量。

速记

partial = 把总变的那部分,提前固定住。
它让回调、并行映射、排序/过滤等写法短小、清晰、可复用;定义类内“带固定实参的方法”时,用 partialmethod 更优雅。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MonkeyKing.sun

对你有帮助的话,可以打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值