转自:https://blog.csdn.net/appleyk/article/details/77609114

一、什么是偏函数?

(1)在Python的functools模块众多的功能中,其中有一个就是偏函数,我们称之为 partial function

模块的概念我们下一篇在细讲。

(2)我们都听过偏将军吧,在三国时代的官制中,系将军的辅佐,与裨将军两者都为杂号将军;今天我们要讲的偏函数,其实是函数的辅佐,什么意思呢,我们借助Python的help帮助函数,看一下:

这里我们主要说下红色圈的意思:

partial 一共有三个部分:

(1)第一部分也就是第一个参数,是一个函数,这个函数可以是你定义的,也可以是Python内置函数

(2)第二部分是一个可变参数,*args,比如内置函数max的参数就是一个可变参数,max(1,2,3,4,5)=5

(3)第三部分是一个关键字参数,比如内置函数int的第二个参数就是命名关键字参数,默认base=10,表示int转换时默认是10进制的:

partial函数的作用就是:将所作用的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。

文字描述显得有些无力,我们下面就开始讲一下,偏函数是怎么用的

二、偏函数的使用

A、偏函数的第二个部分(可变参数),按原有函数的参数顺序进行补充,参数将作用在原函数上,最后偏函数返回一个新函数(类似于,装饰器decorator,对于函数进行二次包装,产生特殊效果;但又不同于装饰器,偏函数产生了一个新函数,而装饰器,可改变被装饰函数的函数入口地址也可以不影响原函数)

案例:我们定义一个sum函数,参数为*args可变,计算这些可变参数的和。

扩展:我们想要对sum函数求和后的结果,再加上10加上20甚至加更多,得到一个新的结果

实现:我们分别用decorator和partial来实现,对比一下二者的区别

(一)装饰器 decorator 实现

我们上一篇,刚刚学过decorator,所以这里,我们直接看demo,应该会觉得很容易上手和理解:

test.py

  1. # /usr/bin/env Python3

  2. # -*- encoding:UTF-8 -*-

  3. from functools import wraps

  4. def sum_add(*args1): #我们要给我们的装饰器decorator,带上参数

  5. def decorator(func):

  6. @wraps(func) #加上这句,原函数func被decorator作用后,函数性质不变

  7. def my_sum(*args2): #注意,参数要和原函数保持一致,真正实行扩展功能的是外层的装饰器

  8. my_s = 0

  9. for n in args1:

  10. my_s = my_s +n #这个是我们新加的求和结果

  11. return func(*args2) + my_s #这个,我们在原求和函数的结果上再加上s,并返回这个值

  12. return my_sum #返回my_sum函数,该函数扩展原函数的功能

  13. return decorator #返回我们的装饰器

  14. @sum_add(10,20) #启用装饰器 对sum函数进行功能扩展

  15. def sum(*args):

  16. s = 0

  17. for n in args:

  18. s = s+n

  19. return s

  20. print(sum(1,2,3,4,5))

  21. print(sum.__name__)

sum(1,2,3,4,5)返回的结果绝不是15,这样就失去了装饰器存在的意义,当然,这里,我们知道,sum最后返回的值应该是10+20+15 = 45,这样一来,我们的decorator就实现了我们想要的扩展功能,最后,发现,原函数sum的name属性,仍然是sum,说明,这种装饰扩展功能,不影响我们的原函数:

(二)偏函数 partial function 实现

这才是我们本篇的重点,准备好了,我们就开始:

我们先来看下普通函数,我们是怎么来实现

A:普通函数可变参数顺序执行

  1. # /usr/bin/env Python3

  2. # -*- encoding:UTF-8 -*-

  3. def sum(*args):

  4. s = 0

  5. for n in args:

  6. s = s + n

  7. return s

  8. print(sum(10,20)+sum(1,2,3,4,5))

我们如果想实现+10+20的效果,必须写两遍sum,这样写,显然是最易懂的,但是,却显得很邋遢不专业,我们看下结果:

B:普通函数可变参数加关键字参数组合

针对上面的A过程,我们改下代码,使我们的代码看起来稍显复杂,但是略显专业:

  1. # /usr/bin/env Python3

  2. # -*- encoding:UTF-8 -*-

  3. def sum(*args,**others):

  4. s = 0

  5. for n in args:

  6. s = s + n

  7. s1 = 0

  8. for k in others:

  9. s1 = s1 + others[k] #我们还要算一下,关键字参数里蕴藏的求和结果,k是dict中的关键字key

  10. return s+s1 #最终,我们实现扩展功能,顺序参数和关键字参数结果相加

  11. D= {'value1':10,'value2':20}

  12. print(sum(1,2,3,4,5,**D))

代码看起来,是显得专业了,但是感觉冗余,没必要,复杂不是我们Python的风格,我们看下B的结果:

C:偏函数可变参数顺序填充一步到位

上面A和B我们都说过了,这两种方式都不好,显然,这么简单的事情,我们不必麻烦decorator了,那我们还有办法没?有,Python,给我们提供了偏函数,来吧,主角登场:

提示:两种使用partial功能方式

(1)import functools                        -->functools.partial(func,*args)
(2)from   functools import partial -->partial(func,*args)

我们这里选第二种,我们看下demo:

  1. # /usr/bin/env Python3

  2. # -*- encoding:UTF-8 -*-

  3. from functools import partial

  4. def sum(*args):

  5. s = 0

  6. for n in args:

  7. s = s + n

  8. return s

  9. sum_add_10 = partial(sum,10) #10 作用在sum第一个参数的位置

  10. sum_add_10_20 = partial(sum,10,20) #10 20 分别作用在sum第一个和第二个参数的位置

  11. print('A____________我们看下原函数sum的函数地址入口:')

  12. print(sum)

  13. print('B______我们看下partial函数返回函数的地址入口:')

  14. print(partial(sum,10))

  15. print(sum_add_10(1,2,3,4,5)) # --> 10 + 1 + 2 + 3 + 4 + 5 = 25

  16. print(sum_add_10_20(1,2,3,4,5)) # --> 10 + 20 + 1 + 2 + 3 + 4 + 5 = 45

上面,可以看出,我们针对sum函数的求和结果,再加上10,或者加10加20,甚至加更多,都是可以通过偏函数来实现的,注意偏函数的第二部分,参数是可变的,是按顺序走的,因此,偏函数产生的新函数,sum_add_10 实际上等同于sum(10,*args):

通过几个例子,我们最终发现,还是偏函数比较方便,一行代码就搞定了,而且新定义的函数,可以根据函数名很容易知道,这个函数扩展的原函数是哪个,实现的效果是什么:

B、偏函数的第三个部分(关键字参数),按原有函数的关键字参数进行填补,参数将作用在原函数上,最后偏函数返回一个新函数

案例:我们定义一个mod求余函数,两个参数,一个是被除数,一个是除数,除数我们这里用命名关键字参数表示,默认值2

扩展:我们的除数不固定,可以是对2就行求余,也可以对3,对4,总之我们需要指定除数的值

返回结果: True 或 False

实现:原函数实现和partial函数实现

demo如下:

  1. # /usr/bin/env Python3

  2. # -*- encoding:UTF-8 -*-

  3. import functools

  4. def mod(m,*,key=2):

  5. return m % key == 0

  6. mod_to_2 = functools.partial(mod,key=2)

  7. print('A__3___使用原函数的默认关键字参数对2进行求余:')

  8. print(mod(3)) #对2进行求余-- 原函数 使用默认参数

  9. print('B__3___使用偏函数对2进行求余:')

  10. print(mod_to_2(3)) #对2进行求余-- 新函数 --偏函数产生

  11. mod_to_5 = functools.partial(mod,key=5)

  12. print('C__25___使用原函数的关键字参数对5进行求余:')

  13. print(mod(25,key=5)) #对5进行求余 -- 原函数

  14. print('D__25___使用偏函数对5进行求余:')

  15. print(mod_to_5(25)) #对5进行求余 -- 新函数--偏函数产生

我们看下结果:

我们发现,实际上,偏函数的作用,其实和原函数差不多,只不过,我们要多次调用原函数的时候,有些参数,我们需要多次手动的去提供值,比如上述的对5进行求余,如果我们想知道,15,45,30这些数是否能够被5整除,那么,我们用原函数的话,就需要写三次,key=5,然而,我们用偏函数的话,只需要重复调用新产生的函数mod_to_5(15 or 45 or 30)即可,至于除数5,偏函数已经为我们设定了,因此:

当函数的参数个数太多,需要简化时,使用 functools.partial 可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。当然,decorator也可以实现,如果,我们不嫌麻烦的话。

结束语:

一种方案行不通的话,我们就换另一种方案,如果两种方案都行得通的话,我们确保那个最简单高效的方案,这样一来,最后受益的将是我们自己。

Python3学习(18)--偏函数(Partial)相关推荐

  1. Python3学习(18)--偏函数(Partial) --转载存地址

    由于最近出差,没有时间更,  倒不是忙,而是费心,项目其实并不难,主要是涉及钱的地方谈技术略显苍白:没有技术解决不了的问题,但是钱没到位,没人愿意无偿给你提供技术,算是停更一周后的,吐槽吧. 赶上今天 ...

  2. python基础第三章选择结构答案-python3 学习笔记(二)选择结构、循环结构

    python3 学习笔记 python 优雅 明确 简单 1.选择结构 (1)简单判断 if else 使用格式: if  条件: 表达式1 else: 表达式2 (2)多条件判断 elif 使用格式 ...

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

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

  4. 实验楼python3中挑战一_实验楼python3学习挑战项目

    实验楼python3学习挑战项目 在实验楼学习python3做的挑战项目做的代码整理. 链接:https://www.shiyanlou.com/courses/596 1.圆的面积 题目: 能够计算 ...

  5. Python3学习笔记之-学习基础(第三篇)

    Python3学习笔记之-学习基础(第三篇) 文章目录 目录 Python3学习笔记之-学习基础(第三篇) 文章目录 一.循环 1.for循环 2.while循环 3.break,continue 二 ...

  6. A Byte of Python3 学习笔记

    A Byte of Python3 学习笔记 第七章 控制流 1.if语句(带输入函数) 2.while语句 3.for循环 4.break.continue.return的区别 第八章 函数 8.1 ...

  7. 【ML/DL】python3学习《机器学习实战》书中的报错及解决办法

    python3学习<机器学习实战>书中的报错及解决办法(更新中) <机器学习实战>是一本很不错的书,其采用的是py2的语法格式,在用最新的python3.6编写代码的过程中,书 ...

  8. Python3 学习笔记

    Python3 学习笔记 1.基础语法 1.1 字符串操作 title() 将单词首字母改为大写 upper() 所有字母改为大写 lower() 所有字母改为小写 str1+str2 字符串通过'+ ...

  9. python3学习(3):ID 遍历爬虫

    从python3学习(2)中可知所有爬取的网站URL只有在结尾处有区别,因此,可以利用该弱点来遍历访问所有URL. ### 二. ID 遍历爬虫,利用网站结构的弱点,轻松访问所有内容. # Downl ...

最新文章

  1. 11张信用卡20多万全部逾期还不上,每天电话追债,怎么办?
  2. JS滚动条位置,顶部,底部,触发事件
  3. ei会议论文录用但不参加会议_美国研究生和博士申请论文发表真的很重要吗?...
  4. python读压缩文件内容_Python读写压缩文件的方法
  5. 为什么大学要学一堆纸上谈兵的课程?(转)
  6. 信度和效度经典例子_浅析经典目标检测评价指标--mmAP(一)
  7. 双链路是什么意思_双链路DVI是什么意思 工作原理是什么
  8. 密歇根州立大学计算机专业排名,密歇根州立大学优势专业及优势专业排名(QS世界排名)...
  9. 见过这么有才的笑话吗?
  10. 怎么看神经网络过早收敛_你的神经网络真的收敛了么?
  11. C++ 面向对象高级开发(侯捷)
  12. 小喇叭上面有红叉,显示未插入扬声器或耳机,电脑没声音
  13. 对办公文档加密 到了外部计算机就无法打开,使用文件夹加密超级大师加密了文件,更换电脑后加密文件打不开了怎么办?...
  14. 计算机专业支教,【计算机】梦缘·夏季支教志愿招募
  15. 男友是程序员,看着他压力大我难受。有哪些缓解压力的好方法?
  16. IDE+vim,提高开发效率
  17. 看电影的计算机配置,2160p的电影需要什么电脑配置看才流畅?
  18. 创业这10种死法,你死在哪一种了
  19. Python爬取和分析旅游数据
  20. STM32F051——USART

热门文章

  1. 蒙特卡罗方法的代码实现——python
  2. 图的存储方式 // oj3116 oj3117 oj3118 oj3467
  3. 汇编语言--SS 和 SP
  4. 【TV Picture Quality - 06】TV PQ概念定义汇总(一)
  5. 火狐主页被hao123劫持
  6. golang:解析HTTP请求参数
  7. 魅蓝s6 android系统版本,魅蓝s6处理器相当于骁龙多少-与非网
  8. Trends in Cognitive Sciences综述:学习和记忆中的背景推理
  9. 现代计算机图形学入门(三)——光栅化
  10. 老板应该是布局者,而不是做事者(经典)