functools模块

functools模块是为了高阶函数(该高阶函数的定义为作用于或返回其它函数的函数)而设置的。一般来说,任何可调用的对象在该模块中都可被当做函数而处理。

这是在关于functools模块的功能总结,但很是晦涩,
换句话说,functools模块支持函数式编程,即将自定义的函数引用作为参数传递给functools模块下某一个功能函数,得到一个可执行的函数对象

partial

functool.partial返回一个调用的partial对象,使用方法按照partial(func, *args, **kwargs)调用。

其发挥的作用在于固定部分参数,从而减少可调用对象的参数个数

from functools import partialdef spam(a, b, c, d):print(a, b, c, d)s1 = partial(spam, 1)  # a = 1
s1(1, 2, 3)  #  1, 1, 2, 3s2 = partial(spam, 1, 2, d=12)
s2(1)  # 1, 2, 1, 12

可以看出 partial() 固定某些参数并返回一个新的callable对象。这个新的callable接受未赋值的参数, 然后跟之前已经赋值过的参数合并起来,最后将所有参数传递给原始函数。


例子1:根据一个基点来排序点列表集[^乱序]

# coding: utf-8
from functools import partial
from operator import itemgetter
import mathorigin = (0, 1)  # 基点
points = [(7, 1), (6, 3), (3, 3)]  # 待排序点集def distance(p1, p2):"""return the distance between p1 and p2"""x1, y1 = p1x2, y2 = p2return math.hypot(x1-x2, y1-y2)sorted_points = sorted(points, key=partial(distance, origin))print(sorted_points)  # [(3, 3), (6, 3), (7, 1)]

其实,我们是可以通过sorted(points, key=lambda x: distance(x, origin))来实现同样的功能


partial专注于设计模式,从而提高代码的健壮性。

例子2:如下代码使用 multiprocessing.apply_async() 来异步计算一个结果值, 然后这个值被传递给一个接受一个result值和一个可选logging参数的回调函数,通过partial固定了log对象。

from functools import partial
from multiprocessing import Pool
import loggingdef output_result(result, logger=None):"""output result"""if logger is not None:logger.debug("%d", result)def add(x, y):return x+yif __name__ == '__main__':args = (1, 2)logging.basicConfig(level=logging.DEBUG)logger = logging.getLogger(__name__)p = Pool()  # 工作进程的数量默认使用os.cpu_count()返回的数量p.apply_async(add, args, callback=partial(output_result, logger=logger))  # 异步执行p.close()p.join()  # 主进程需等待所有子进程执行完毕才关闭

例子3:用socketserver模块编写一个易用的网络服务器,实现echo功能

from socketserver import TCPServer, StreamRequestHandlerclass TCPEchoHandler(StreamRequestHandler):"""c/s下实现echo请求"""def __init__(self, prefix, *args, **kwargs):self.prefix = prefixsuper(TCPEchoHandler).__init__(self, *args, **kwargs)def handle(self):"""请求处理"""# rfile带有缓冲区, 支持分行读取for line in self.rfile:response = 'server get :{data}'.format(data=line.encode('utf-8'))self.wfile.write(response)if __name__ == '__main__':addr = ('localhost', 10030)server = TCPServer(addr, TCPEchoHandler)server.serve_forever()

假设此时,我们需要额外的为TCPEchoHandler增加一个属性,按照常识我们可能会这么做:

那如何使得server对象中接收这一属性呢?partial就派上用场了

server = TCPServer(addr, partial(TCPEchoHandler, prefix=b"TCPEchoHandler: \t"))

*特别说明

  • 大部分的partial实现的高阶函数引用是能够采用lambda表达式来替换的(针对于运行时有产出值的情况, 例如排序用到的sorted函数的参数key);
  • partiallambda相比较拥有较高的性能;
  • lambda语义相对较模糊,可读性不高。

源码分析

在分析源码前,我们必须知道

Python中函数也是对象,意味着可以为函数对象动态添加属性

>>> def test(key1, key2):pass
>>> type(test)
<class 'function'>
>>> test.kwargs = {'key2': 1}
>>> getattr(test, kwargs)
Traceback (most recent call last):File "<pyshell#45>", line 1, in <module>getattr(test, kwargs)
NameError: name 'kwargs' is not defined
>>> getattr(test, 'kwargs')
{'key2': 1}

通过以上推导可知,将固定参数[^(不定参数或关键字参数)]重载到原函数即可实现partial

这时我们再来查看partial的源码:

def partial(func, *args, **keywords):"""New function with partial application of the given argumentsand keywords."""if hasattr(func, 'func'):args = func.args + argstmpkw = func.keywords.copy()tmpkw.update(keywords)keywords = tmpkwdel tmpkwfunc = func.funcdef newfunc(*fargs, **fkeywords):newkeywords = keywords.copy()newkeywords.update(fkeywords)return func(*(args + fargs), **newkeywords)newfunc.func = funcnewfunc.args = argsnewfunc.keywords = keywordsreturn newfunc
def add(m, n):return m*nif __name__ == '__main__':p = partial(add, n=10)print(p(1))

newfunc[^函数对象]将func、固定的不定参数args、固定的关键字参数keywords封装为自己的属性,利用闭包将固定参数与非固定参数(fargs, fkeywords)进行拼接,然后返回该新构造的func对象的调用。


转载于:https://www.cnblogs.com/kisun168/p/11559960.html

Python partial相关推荐

  1. python partial函数

    Python 提供了一个 functools 的模块,该模块为高阶函数提供支持,partial 就是其中的一个函数,该函数的形式如下: functools.partial(func[,*args][, ...

  2. python函数局部变量_Python局部函数– functoolspartial()

    python函数局部变量 什么是Python局部函数? (What is a Python Partial Function?) Sometimes a function accepts multip ...

  3. Python基础教程,Python神仙级入门教程(非常详细)

    Python 是一门开源免费.通用型的脚本编程语言,它上手简单,功能强大,坚持「极简主义」. Python 类库(模块)极其丰富,这使得 Python 几乎无所不能,不管是传统的 Web 开发.PC ...

  4. 中科大+快手出品 CIRS: Bursting Filter Bubbles by Counterfactual Interactive Recommender System 代码解析

    文章目录 前言 论文介绍: 代码介绍: 代码: 一. CIRS-UserModel-kuaishou.py 0. get_args() 解析参数 1. create_dir() 2. Prepare ...

  5. ApacheCN《Sklearn 与 TensorFlow 机器学习实用指南》 第11章 项目训练深层神经网络(梯度消失与梯度爆炸,选择初始化,选择激活函数)

    原文:https://www.jishux.com/p/52b468ceb5722ca5 第11章 训练深层神经网络 来源:ApacheCN<Sklearn 与 TensorFlow 机器学习实 ...

  6. Functional Programming函数式编程

    概论 在过去的近十年的时间里,面向对象编程大行其道.以至于在大学的教育里,老师也只会教给我们两种编程模型,面向过程和面向对象.孰不知,在面向对象产生之前,在面向对象思想产生之前,函数式编程已经有了数十 ...

  7. Python偏相关(Partial Correlation)或者部分相关性系数计算实战:偏相关性(Partial Correlation)计算及结果解读

    Python偏相关(Partial Correlation)或者部分相关性系数计算实战:偏相关性(Partial Correlation)计算及结果解读 目录

  8. python functools.wraps functools.partial实例解析

    一:python functools.wraps 实例 1. 未使用wraps的实例 #!/usr/bin/env python # coding:utf-8def logged(func):def ...

  9. python函数编程-偏函数partial function

    python函数编程-偏函数partial function 一般的,通过设定函数参数的默认值,可以减低函数调用的难度.比如:int()函数可以把字符串转换成整数: >>> int( ...

最新文章

  1. 11: facebook原生登录
  2. python写用用户名密码程序_Python创建用户名和密码程序
  3. 带卷积核的神经网络的迭代次数与收敛标准的关系
  4. .NET实现应用程序登录Web页
  5. Boost:bind绑定作为一个组合的测试程序
  6. Wireshark个人实战总结
  7. RMQ(求区间最值问题)
  8. 贝叶斯定理到贝叶斯滤波器
  9. IIS 500 错误解决
  10. 【BZOJ3505】[Cqoi2014]数三角形 组合数
  11. ModelSim仿真实例教程
  12. MCMC蒙特卡洛算法
  13. CTFshow wbe41 教你写脚本
  14. mysql表删除后恢复
  15. 推荐系统之itemCF
  16. 花一个星期时间呕心沥血整理出高频软件测试/自动化测试面试题和答案
  17. Excel数据快速录入技巧分享
  18. Mac 终端 oh-my-zsh 配置,内含解决oh-my-zsh 下载不下来的方法
  19. 盘点数据分析师笔试题 你会做几道?
  20. 【服务器管理】mount.nfs: Stale file handle的解决办法

热门文章

  1. Linux入门:usermod - 修改用户帐户信息
  2. 如何确定恶意软件是否在自己的电脑中执行过?
  3. 关于某题左列定宽右列宽度自适应布局的学习
  4. Linux下testlink安装
  5. ZH奶酪:PHP遍历目录/文件的3种方法
  6. 蓝桥杯 算法训练 区间k大数查询(水题)
  7. 当有多个设备online时,命令行窗口通过adb连接指定设备方法
  8. Qt、GTK 和KDE、GNOME的关系-转
  9. PAT 乙级 1037. 在霍格沃茨找零钱(20)Java版
  10. 1029. 旧键盘(20)-PAT乙级真题