前一段时间学习了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包裹的更多相关文章

  1. Python中functools模块函数解析

    Python自带的 functools 模块提供了一些常用的高阶函数,也就是用于处理其它函数的特殊函数.换言之,就是能使用该模块对可调用对象进行处理. functools模块函数概览 functool ...

  2. Python使用functools模块中的partial函数生成偏函数

    所谓偏函数即是规定了固定参数的函数,在函数式编程中我们经常可以用到,这里我们就来看一下Python使用functools模块中的partial函数生成偏函数的方法 python 中提供一种用于对函数固 ...

  3. Python中optionParser模块的使用方法[转]

    本文以实例形式较为详尽的讲述了Python中optionParser模块的使用方法,对于深入学习Python有很好的借鉴价值.分享给大家供大家参考之用.具体分析如下: 一般来说,Python中有两个内 ...

  4. Python中的模块介绍和使用

    在Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一 ...

  5. Python中time模块详解

    Python中time模块详解 在平常的代码中,我们常常需要与时间打交道.在Python中,与时间处理有关的模块就包括:time,datetime以及calendar.这篇文章,主要讲解time模块. ...

  6. Python 中包/模块的 `import` 操作

    版权声明:博客为作者原创,允许转载,但必须注明原文地址: https://www.cnblogs.com/byronxie/p/10745292.html 用实例来说明 import 的作用吧. 创建 ...

  7. 正则表达式与Python中re模块的使用

    正则表达式与Python中re模块的使用 最近做了点爬虫,正则表达式使用的非常多,用Python做的话会用到re模块. 本文总结一下正则表达式与re模块的基础与使用. 另外,给大家介绍一个在线测试正则 ...

  8. python中的模块和包

    模块 一 什么是模块 模块就是一组功能的集合体,可以通过导入模块来复用模块的功能. 比如我在同一个文件夹定义两个.py文件,分别命名为A.py和B.py,那么可以通过在A文件里通过import B来使 ...

  9. python中argparse模块用法实例详解

    python中argparse模块用法实例详解 这篇文章主要介绍了python中argparse模块用法,以实例形式较为详细的分析了argparse模块解析命令行参数的使用技巧,需要的朋友可以参考下 ...

随机推荐

  1. python全栈开发-Day6 字符编码

    python全栈开发-Day6 字符编码 一 .了解字符编码的知识储备 一 .计算机基础知识 二 .文本编辑器存取文件的原理(nodepad++,pycharm,word) #1.打开编辑器就打开了启 ...

  2. C++实现Date日期类

    定义一个Date类,包含三个属性年.月.日 实现了如下功能: 年月日的增加.减少:2017年10月1日加上100个月30天是2025年5月31日 输出某天是星期几:2017年10月1日是星期日 判断某 ...

  3. es6使用技巧

    ##1.通过参数默认值实现强制参数 ES6 的参数默认值只有在真正使用时才会求值.这可以让你强制确保提供参数: /** * Called if a parameter is missing and * ...

  4. [Chrome 浏览器快捷键]——“你是键盘党吗?”

    标签页和窗口快捷键 操作 快捷键 打开新窗口 Ctrl + n 在隐身模式下打开新窗口 Ctrl + Shift + n 打开新的标签页,并跳转到该标签页 Ctrl + t 重新打开最后关闭的标签页, ...

  5. PHP 相对完整的分页

    效果链接http://love.bjxxw.com/oejiaoyou/pubu/zhaopian.php php 分页 <?php /* * * * 说明 吉海波 2015/9/17 * $p ...

  6. 每日冲刺报告——Day5(Java-Team)

    第五天报告(11.6  周一) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://git ...

  7. 基于微信小程序的失物招领系统的Postmortem

    基于微信小程序的失物招领系统的Postmortem 设想和目标 1.我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 对于我们团队要解决的问题和实现的功能在项目开始就 ...

  8. 2017-2018-1 我爱学Java 第一周 作业

    构建之法 成员及分工 内容简介 作者简介 分章学习及问题 第一章 概论 第二章 个人技术和流程 第三章 软件工程师的成长 第四章 两人合作 第五章 团队和流程 第六章 敏捷流程 第七章 实战中的软件工 ...

  9. Python upper()方法

    描述 Python upper() 方法将字符串中的小写字母转为大写字母. 语法 upper()方法语法: str.upper() 参数 NA. 返回值 返回小写字母转为大写字母的字符串. 实例 以下 ...

  10. scrapy 避免被ban

    1.settings.pyCOOKIES_ENABLED = False DOWNLOAD_DELAY = 3 ROBOTSTXT_OBEY = Falseip代理池设置 IPPOOL = [{'ip ...