python中 functools模块 闭包的两个好朋友partial偏函数和wraps包裹
前一段时间学习了python当中的装饰器,主要利用了闭包的原理。后来呢,又见到了python当中的functools模块,里面有很多实用的功能。今天我想分享一下跟装饰器息息相关的两个函数partial和wraps,这两个好伙伴可以说是非常实用。
1 partial偏函数: 这个函数可以帮助我们对一个接收多个参数的函数绑定其中几个参数,返回一个对象,调用这个对象的时候只传给他剩下的参数就可以。它实现了好像闭包才能实现的功能。有的时候可以代替闭包来使用。
不理解??没关系,听我慢慢说!
比如,我们现在想要编写一个函数帮助我们计算直线在坐标系上的y值。 直线方程y = a*x+b。大家请看代码:
def line( a , b , x ):
return a*x + b if __name__ == '__main__':
y1 = line( 10 , 20 , 30)
y2 = line( 10 , 20 , 35)
y3 = line( 10 , 20 , 7)
这个函数能够帮助我们完成功能,给定直线方程的系数a和b,再给定x就能计算出y。
但是我们发现,如果我们想多次利用同一条直线,比如 y = 10*x+20,我们每次传不同的x进去的时候a和b的值也必须传进去,我们重复做了很多工作。
我们怎么样能获得一条a和b指定的直线呢?我们只传进去x就能获取y,相同的直线不用每次都指定a和b??当然可以,用闭包就能实现!
如果还不会闭包的知识的伙伴,你们可以参考这篇博文学习一下闭包:http://www.cnblogs.com/Lin-Yi/p/7305364.html
我们先用闭包实现,上代码!
def getLine( a , b ):
def line( x ):
return a*x + b
return line if __name__ == '__main__':
line1 = getLine( 10,20 )
y1 = line1(5)
y2 = line1(6)
y3 = line1(7)
在这个闭包例子中,我们调用getLine传入a和b,之后我们拿到了内部的line函数,我们再调用line的时候只要给他传入x就可以,这样我们能重复利用同一条直线。
但是其实编写闭包挺麻烦的,我们要写内涵数外函数,而且很多好伙伴可能不理解闭包是怎么回事。这个时候福利来了!!!!!
我们用partial偏函数来实现一个绑定参数的直线!!看代码!
import functools def line( a, b, x ):
return a*x + b if __name__ == '__main__':
#拿到了 y= 10*x + 20
line1 = functools.partial( line, 10 , 20 ) y1 = line1(30)
y2 = line1(35)
y2 = line1(35)
y3 = line1(40)
本来呢,line函数接收三个参数a b和x,但是用partial,把line函数的引用穿进去,之后跟着两个参数,这就代表我要把line函数的前两个参数绑定我传入的指定数值10和20,然后返回一个对象给了line1
我们再调用line1的时候只要传入x就可以执行line函数了!!!
怎么样!是不是很神奇,我们用partial偏函数绑定了一个函数的部分参数,然后拿到一个函数对象,帮我们实现了闭包才能实现的效果!
2 wraps包裹: 帮助我们实现装饰器中,目标函数对象的属性迁移。
不理解??刚开始我也不理解~ . ~........ 那就听我说说~也许就懂啦!
上一次在探讨装饰器的时候,最后一个例子中留了一个问题没有解决,问题就是,我们用装饰器对目标函数dest进行装饰,用@decorator的时候,把目标函数dest传入了装饰器decorator,装饰器把内部函数inner的引用返回给了目标函数名dest。当我们再调用dest的时候实际上调用了装饰器返回的内部函数inner的实例对象。如果我们查看一下dest.__name__和dest.__doc__等等这些属性,发现我们获得的是inner的属性不是原本我们想要的dest的属性。
看我的描述很糊涂吧,我们来一段代码!看一下,装饰器带来了什么问题:
def decorator(func):
def inner( *args ,**kwargs ):
print("装饰器的前置业务逻辑")
res = func( *args ,**kwargs ) #在这里执行目标函数
print("装饰器的后置业务逻辑")
return res
return inner @decorator #这里相当于发生了 dest = decorator( dest )
# 把目标函数dest传进去给了func,返回来的inner给了dest
def dest(): #之后再执行dest 其实执行了inner
print("这里是目标函数dest") if __name__ == '__main__':
print(dest.__name__) #inner
我们用decorator装饰器对dest目标函数装饰之后,再查看dest.__name__ 却得到了inner,,因为内涵数返回给了dest保存,再调用dest其实就是调用了inner
这是正确的却不是我们想要的。我们抛开装饰器,在外部看来,我们还是想要得到一致性的结果,我指向要我自己的属性,怎么办??
ok!wraps能够帮我们实现属性的迁移!
上一段代码!
import functools
def decorator(func):
#functool模块的wraps函数传入目标函数,他能帮我们把目标函数的所有属性迁移给内涵数
@functools.wraps(func)
def inner( *args ,**kwargs ):
print("装饰器的前置业务逻辑")
res = func( *args ,**kwargs ) #在这里执行目标函数
print("装饰器的后置业务逻辑")
return res
return inner @decorator #这里相当于发生了 dest = decorator( dest )
# 把目标函数dest传进去给了func,返回来的inner给了dest
def dest(): #之后再执行dest 其实执行了inner
print("这里是目标函数dest") if __name__ == '__main__':
#这是再查看属性的时候 就保持了一致性,wraps帮助我们把目标函数的属性迁移了
print(dest.__name__) #dest
和上面的例子只有一行代码的区别,在inner函数前加上了@functools.wraps(func)
把目标函数传给wraps,用wraps对inner进行装饰,它帮助我们把目标函数的属性全都复制过来了。让外部调用者看来保持了一致性!
python中 functools模块 闭包的两个好朋友partial偏函数和wraps包裹的更多相关文章
- Python中functools模块函数解析
Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数.换言之,就是能使用该模块对可调用对象进行处理. functools模块函数概览 functool ...
- Python使用functools模块中的partial函数生成偏函数
所谓偏函数即是规定了固定参数的函数,在函数式编程中我们经常可以用到,这里我们就来看一下Python使用functools模块中的partial函数生成偏函数的方法 python 中提供一种用于对函数固 ...
- Python中optionParser模块的使用方法[转]
本文以实例形式较为详尽的讲述了Python中optionParser模块的使用方法,对于深入学习Python有很好的借鉴价值.分享给大家供大家参考之用.具体分析如下: 一般来说,Python中有两个内 ...
- Python中的模块介绍和使用
在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一 ...
- Python中time模块详解
Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...
- Python 中包/模块的 `import` 操作
版权声明:博客为作者原创,允许转载,但必须注明原文地址: https://www.cnblogs.com/byronxie/p/10745292.html 用实例来说明 import 的作用吧. 创建 ...
- 正则表达式与Python中re模块的使用
正则表达式与Python中re模块的使用 最近做了点爬虫,正则表达式使用的非常多,用Python做的话会用到re模块. 本文总结一下正则表达式与re模块的基础与使用. 另外,给大家介绍一个在线测试正则 ...
- python中的模块和包
模块 一 什么是模块 模块就是一组功能的集合体,可以通过导入模块来复用模块的功能. 比如我在同一个文件夹定义两个.py文件,分别命名为A.py和B.py,那么可以通过在A文件里通过import B来使 ...
- python中argparse模块用法实例详解
python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...
随机推荐
- 关于Videodownload helper的下载问题
Videodownload helper是火狐浏览器的一个视频音频嗅探插件, 解压文件的时候处于解压状态还没有解压完的时候不能关闭原来的窗口 所以这个下载软件也同理.没有下载完一个视频之前不能把这个窗 ...
- 理解Spring中的IOC和AOP
我们是在使用Spring框架的过程中,其实就是为了使用IOC,依赖注入和AOP,面向切面编程,这两个是Spring的灵魂. 主要用到的设计模式有工厂模式和代理模式 IOC就是典型的工厂模式,通过ses ...
- 【阿里聚安全·安全周刊】500万台Android设备受感染|YouTube封杀枪支组装视频
本周的七个关键词: 500万Android 设备受感染丨 黑客将矛头指向无线传输协议 丨 YouTube封杀枪支视频 丨 AMD将发布补丁 丨 Gooligan Android 僵尸网络 丨 N ...
- Lucene-01:创建索引
我们在D盘下建一个文件夹叫lucene,lucene内再建两个文件夹,一个叫example,一个叫index01.example文件夹下三个txt文件,a.txt内容为hello java,b.txt ...
- Tomcat下wtpwebapps文件夹 和 webapps文件夹区别
这两者其实没有区别.都是项目部署路径 webapps : tomcat默认部署路径 wtpwebapps : eclipse默认部署路径 只不过Tomcat6将wtpwebapps作为了默认路径,如果 ...
- 关于 Git使用的全面总结 —— 致敬Git之父Linux
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px ".PingFang SC"; color: #454545 } p.p2 ...
- 谁说 JavaScript 简单的?
这里有一些 Javascript初学者应该知道的技巧和陷阱.如果你已经是专家了,顺便温习一下. Javascript也只不过是一种编程语言.怎么可能出错嘛? 1. 你有没有尝试给一组数字排序? Jav ...
- 如何打包静态库.a文件 iOS
代码调试好了开始打包成sdk,下面是将要打包的FRSDK代码(FRSDK.h暴露在外面有别人调用) 1.创建新工程(Xcode File-New-Project) 2.把下面的红色框的东西移除 3.将 ...
- Linux下的指令:find,which
1. 在Linux系统下,使用find来查找文件: find [path] [condition] [operation] path指定了在哪个目录查找,condition限定了查找条件,operat ...
- Visual Studio 2017 Key 激活码
Visual Studio 2017(VS2017) 企业版 Enterprise 注册码:NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Visual Studio 2017(VS201 ...