python学习之---匿名函数,返回函数,偏函数

1. 返回函数:

所谓的返回函数,指的是函数作为返回值。高阶函数除了可以接受函数作为参数外,同样可以接受函数作为结果返回。以下是一个可变参数的求和例子,一般求和函数是如此这般定义的:

1 >>> def sum(*args):
2 ...     ax = 0
3 ...     for x in args:
4 ...         ax += x
5 ...     return ax
6 ... 

以上函数一旦定义,在调用这个函数的时候,只要传入参数就会立刻执行。但是,如果条件需要不要立刻求和,而是在后面的代码中,根据需要再计算该怎么办?可以不返回求和的结果,而是返回求和的函数!

 1 >>> def lazy_sum(*args):
 2 ...     def sum():
 3 ...         ax = 0
 4 ...         for n in args:
 5 ...            ax = ax + n
 6 ...         return ax
 7 ...     return sum
 8 ...
 9 >>>
10 >>> lazy_sum(12)
11 <function sum at 0x7f810add16e0>
12 >>> lazy_sum((1,2,3,4,5,6))
13 <function sum at 0x7f810add17d0>
14 >>>
15 KeyboardInterrupt
16 >>># 以上是调用lazy_sum()函数的结果返回的不是求和的结果,而是求和函数

但是该如何才能够返回结果呢?演示如下:

1 >>> result = lazy_sum(12,13,14,15,16,17,18,19)
2 >>> result
3 <function sum at 0x7f810add17d0>
4 >>> #其实result现在是一个返回函数,要再调用该函数才可以返回结果
5 ...
6 >>> result()
7 124

在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:

1 >>> result1 = lazy_sum(1,2,3,4,5,6,7,8,9,10)
2 >>> result2 = lazy_sum(1,2,3,4,5,6,7,8,9,10)
3 >>> result1
4 <function sum at 0x7f810add16e0>
5 >>> result2
6 <function sum at 0x7f810add1848>
7 >>> result1 == result2
8 False
9 >>> 

如上代码显示:0x7f810add16e0是不等于0x7f810add1848的,因此比较结果为FALSE。但是,什么是“闭包”呢?记得在离散数学里面学习过闭包的知识,关系闭包.......。

2. 闭包:

  注意到返回函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了result()才执行。我们来看一个例子:

1 >>> def get_count():
2 ...     fs = []
3 ...     for i in range(1,10):
4 ...         def f ():
5 ...             return i*i
6 ...         fs.append(f)
7 ...     return fs
8 ... f1,f2,f3 = get_count()

在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都返回了。

你可能认为调用f1()f2()f3()结果应该是149,但实际结果是:

1 >>> f1()
2 9
3 >>> f2()
4 9
5 >>> f3()
6 9

全部都是9!原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为9

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:

 1 >>> def count():
 2 ...     fs = []
 3 ...     for i in range(1,4):
 4 ...         def f(j):
 5 ...             def g():
 6 ...                 return j*j
 7 ...             return g
 8 ...         fs.append(f(i))
 9 ...     return fs
10 ...
11 >>> f1,f2,f3 = count()
12 >>> f1
13 <function g at 0x7f810add19b0>
14 >>> f1()
15 1
16 >>> f2()
17 4
18 >>> f3()
19 9
20 >>> 

缺点是代码较长,可利用lambda函数缩短代码。

3. 匿名函数:

当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

在Python中,对匿名函数提供了有限支持。还是以map()函数为例,计算f(x)=x2时,除了定义一个f(x)的函数外,还可以直接传入匿名函数:

1 >>> map(lambda x : x * x,[1,2,3,4,5,6,7,8,9,])
2 [1, 4, 9, 16, 25, 36, 49, 64, 81]
3 >>> map(lambda x : x * x,range(10))
4 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
5 >>> 

通过对比不难看出,匿名函数lambda x : x * x实际上就是一个求平方的函数:

1 >>> def f(x):
2 ...     return x*x
3 ...
4 >>> f(4)
5 16
6 >>> f(40)
7 1600
8 >>> 

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

1 >>> hanshu = lambda x : x*x*x
2 >>> hanshu
3 <function <lambda> at 0x7f810add1b90>
4 >>> hanshu(45)
5 91125
6 >>> hanshu(450)
7 91125000
8 >>> 

同样,也可以把匿名函数作为返回值返回,比如:

1 >>> def build(x,y):
2 ...     return lambda: x*x + y*y
3 ...
4 >>> build(5,6)
5 <function <lambda> at 0x7f810add1c80>
6 >>> 

4. 偏函数

Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。要注意,这里的偏函数和数学意义上的偏函数不一样。通过设定参数的默认值,可以降低函数调用的难度。而偏函数也可以做到这一点。举例如下:

int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换:

1 >>>
2 >>> int(‘123‘)
3 123
4 >>> int(‘123454567‘)
5 123454567
6 >>> 

int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做N进制的转换:

1 >>> int(‘123‘,base = 8)
2 83
3 >>> int(‘123‘,base = 10)
4 123
5 >>> int(‘123‘,base = 16)
6 291
7 >>> int(‘123123‘,base = 16)
8 1192227
9 >>> 

假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:

 1 >>> def int2(x ,base = 2):
 2 ...     return int(x,base)
 3 ...
 4 >>> int2(100)
 5 Traceback (most recent call last):
 6   File "<stdin>", line 1, in <module>
 7   File "<stdin>", line 2, in int2
 8 TypeError: int() can‘t convert non-string with explicit base
 9 >>> int2(‘100‘)
10 4
11 >>> 

注意:在传入参数的时候,要以字符串的形式传入,否则会报出“TypeError”的类型错误。要使用偏函数的时候还得自己定义,是不是感觉很麻烦?因此,python提供了functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2

1 >>> import functools
2 >>> int2 = functools.partial(int,base = 2)
3 >>> int3 = functools.partial(int,base = 16)
4 >>> int2(‘100‘)
5 4
6 >>> int3(‘100‘)
7 256
8 >>> 

所以,简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:

1 >>> int3(‘100‘,base = 10)
2 100
3 >>> int2(‘100‘,base = 10)
4 100
5 >>> 

最后,创建偏函数时,实际上可以接收函数对象、*args**kw这3个参数,当传入:

1 int2 = functools.partial(int, base=2)

实际上固定了int()函数的关键字参数base,也就是:

1 int2(‘10010‘)

相当于:

1 kw = { base: 2 } 2 int(‘10010‘, **kw)

当传入:

1 max2 = functools.partial(max, 10)

实际上会把10作为*args的一部分自动加到左边,也就是:

1 max2(5, 6, 7)

相当于:

1 args = (10, 5, 6, 7)

2 max(*args)

结果 = 10

时间: 2024-10-06 18:24:22

python学习之---匿名函数,返回函数,偏函数的相关文章

python学习笔记11-python内置函数

python学习笔记11-python内置函数 一.查看python的函数介绍: https://docs.python.org/2/library/ 二.python内置函数 1.abs获取绝对值: 通过python官网查看abs abs(x) Return the absolute value of a number. The argument may be a plain or long integer or a floating point number. If the argument

OpenCV for Python 学习 (二 事件与回调函数)

今天主要看了OpenCV中的事件以及回调函数,这么说可能不准确,主要是下面这两个函数(OpenCV中还有很多这些函数,可以在 http://docs.opencv.org/trunk/modules/highgui/doc/user_interface.html 找到,就不一一列举了),然后自己做了一个简单的绘图程序 函数如下: cv2.setMouseCallback(windowName, onMouse[, param]) cv2.createTrackbar(trackbarName,

python学习笔记7-函数返回值

python学习笔记7-函数返回值 使用return指定isNum()的函数返回值是true或者false, [[email protected] ~]# vim return.py #!/usr/bin/python import os import sys def isNum(s): if s.isdigit(): return True return False for i in os.listdir('/proc'): if isNum(i): print i

python学习之-匿名函数

什么是匿名函数 匿名函数: 没有名字的函数,意味着只能用一次就被回收 匿名函数用 lambda 表示 为何用匿名函数:用于临时使用一次的功能 匿名函数的定义格式 lambda 参数,参数:表达式  #参数规则和有名函数是一样的 lambda x,y:return x+y #这个位置的return是自带的,所以写表达式时候不需要写 表达式解析:匿名函数 + 参数:表达式,将表达式的值用return返回 PS:匿名函数自动有一个返回值,自带return,不能写return,也不能写语句,但是只要有返

Python学习【第九篇】函数

函数 函数是什么? 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上而下实现功能,其往往用一段代码来实现指定功能,开发过程中最常见的操作就是复制粘贴,就是将之前实现的代码块复制到现需功能处,如下: 1 while True: 2 if cpu利用率 > 90%: 3 #发送邮件提醒 4 连接邮箱服务器 5 发送邮件 6 关闭连接 7 8 if 硬盘使用空间 > 90%: 9 #发送邮件提醒 10 连接邮箱服务器 1

Python学习,第八课 - 函数

本次讲解函数,由于内容比较多,小编列了个大纲,主要有一下内容: 1. 函数基本语法及特性 2. 函数参数 3.局部变量 4. 返回值 5.嵌套函数 6.递归 7.匿名函数 8.高阶函数 9.内置函数 1. 函数基本语法及特性 函数的定义:函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 函数的特性: 减少重复代码 使程序变的可扩展 使程序变的易维护 函数的语法定义 直接上代码: # def 是定义函数的关键字 def test():#test既是函数

Python学习入门教程,字符串函数扩充详解

因有用户反映,在基础文章对字符串函数的讲解太过少,故写一篇文章详细讲解一下常用字符串函数.本文章是对:程序员带你十天快速入门Python,玩转电脑软件开发(三)中字符串函数的详解与扩充. 如果您想学习并参与本教程的完善与写作.请在下方讨论区,回复相关问题.一起完善本文章教程的书写. Python字符串常用函数. 声明字符串变量: str = ‘关注做全栈攻城狮,写代码也要读书,爱全栈,更爱生活.’ 下面所有字符串函数函数,是对变量str进行操作: 求字符串长度: 函数使用: 运行结果: 值得注意

Python学习之路第二天——函数

一.Python2.X内置函数表: 注:以上为pyton2.X内置函数,官方网址:https://docs.python.org/2/library/functions.html 二.Python3.X内置函数表: 注:以上为pyton3.X内置函数,官方网址:https://docs.python.org/3.5/library/functions.html 三.自定义函数: def 函数名(参数):     ... 函数体     ... def:是函数的关键字,告诉python解释器这是一

python学习笔记(七)函数

原链接:http://www.cnblogs.com/vamei/archive/2012/06/01/2529500.html#!comments 函数学习遇到了问题 1 #!/usr/bin/env python 2 #coding=utf-8 3 #今天开始学习函数 4 def square_sum(a, b): 5 c = a**2 + b**2 6 return c 7 #其实学习python 过来,一直没有很好的编程的思维,思维总是会受到最初yi脚本的限制 8 #期待突破吧 9 10