Python lambda 与 闭包
来源:互联网 发布:embed js获取播放时间 编辑:程序博客网 时间:2024/06/06 01:27
Lambda
高阶函数可以接收函数做参数,有些时候,我们不需要显式地定义函数,直接传入匿名函数更方便,也就是lambda。
先来看个简单 lambda 函数
>>> lambda x, y : x+y<function <lambda> at 0x102bc1c80>
x 和 y 是函数的两个参数,冒号后面的表达式是函数的返回值,你能一眼看出这个函数就是是在求两个变量的和,但作为一个函数,这里我们暂且给这个匿名函数绑定一个名字,这样使得我们调用匿名函数成为可能。
>>> add = lambda x, y : x+y>>> add<function <lambda> at 0x102bc2140>>>> add(1,2)3
它等同于常规函数
>>> def add2(x, y):... return x+y...>>> add2<function add2 at 0x102bc1c80>>>> add2(1,2)3
匿名函数有个限制,就是只能有一个表达式,不写return,返回值就是该表达式的结果。
例如一个整数列表,要求按照列表中元素的绝对值大小升序排列。
>>> list1 = [3,5,-4,-1,0,-2,-6]>>> sorted(list1, key=lambda x: abs(x) , reverse = False)
排序函数 sorted 支持接收一个函数作为参数,该参数作为 sorted 的排序依据,这里按照列表元素的绝对值进行升序排序。当然,我们也可以用普通函数来实现:
>>> def foo(x):... return abs(x)...>>> sorted(list1, key=foo)
闭包
下面的一段代码定义了两个函数f() 和 g(),在函数f()中把g()作为返回值返回。
这里的g你可以参考C语言中函数的指针来进行理解,它们两个几乎在语义和用法上几乎完全相同。
def g(): print 'g()...'def f(): print 'f()...' return g
我们把函数g()的定义移到f()内部,这样除了f()之外的区域就无法调用g():
def f(): print 'f()...' def g(): print 'g()...' return g
但是对于以下 calc_sum 函数,发现没法把 lazy_sum 移到 calc_sum 的外部,因为它引用了 calc_sum 的参数 lst:
def calc_sum(lst): def lazy_sum(): return sum(lst) return lazy_sum
lst是一个列表,作为参数传进函数calc_sum()中。
此时我们发现无法把函数lazy_sum()移到函数calc_sum()的外面,因为函数lazy_sum()的功能是计算list中所有元素值的和,必须依赖于函数calc_sum()的参数。
如果函数lazy_sum()不在函数calc_sum()里面,则无法取得数据进行计算。
像这种内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。
闭包的特点是返回的函数还引用了外层函数的局部变量。
所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变,例如:
# 希望一次返回3个函数,分别计算1x1,2x2,3x3:def count(): fs = [] for i in range(1, 4): def f(): return i*i fs.append(f) return fsf1, f2, f3 = count()print(f1(),f2(),f3())
你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是 9,9,9。
因为当count()函数返回三个函数时,这三个变量所引用的变量i的值已经变成了3,因为在返回的时候三个函数并没有被调用。
所以此时它们并没有及时计算它们对应的i乘以i的值,等到三个函数都返回时,然后调用三个函数,此时i的值已经为3,计算i*i的值自然就都是9了。
因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量。
将上述程序如下改写后,即可得到结果1,4,9。
def count(): fs = [] for i in range(1, 4): def f(m=i): return m*m fs.append(f) return fsf1, f2, f3 = count()print (f1(), f2(), f3())
- Python lambda 与 闭包
- Lambda与闭包
- c++ lambda闭包
- python3 入门 (三) 函数与lambda表达式、闭包
- lambda表达式的解析(五) Lambda表达式与闭包类型
- Java SE8 Lambda 基础入门---lambda表达式与闭包(closure)
- Python爬虫包 BeautifulSoup 学习(九) 正则表达式与Lambda表达式
- python 匿名函数与lambda
- 【Python笔记】Python的几个高级语法概念浅析:lambda表达式 && 闭包 && 装饰器
- 闭包的概念和闭包与lambda表达式的关系
- python中的lambda表达式的闭包和filter()产生的bug
- Python的lambda函数与排序
- Python的lambda函数与排序
- Python的Lambda函数与排序
- Python的Lambda函数与排序
- python -> lambda与def的区别
- Python的lambda函数与排序
- Python的Lambda函数与排序
- env命令
- 蓝桥杯 算法提高 三个整数的排序
- 基础知识--变量命名规则
- C语言字符串操作符的解读,模拟
- golang之fmt格式占位符总结
- Python lambda 与 闭包
- 面向开发的测试技术(二):性能测试
- 解决android 6.0 动态相机相册定位权限
- java网络编程整理(待续)
- vuejs 报错 Decimals with leading zeros are not allowed in strict mode
- 二叉搜索树的基本操作-04-树7 二叉搜索树的操作集 (30分)
- Android ScrollView Button的显示隐藏
- Android ViewPager 小圆点 + 无限循环 + 动态滑动
- php高版本不再使用mysql_connect()来连接数据库