付公司网站建设费用会计分录,wordpress侧边栏 菜单,国内出色的网站建设公司,四川省住房城乡建设厅网站一、概述
Python是一门多范式的编程语言#xff0c;它同时支持过程式、面向对象和函数式的编程范式。因此#xff0c;在Python中提供了很多符合 函数式编程 风格的特性和工具。 二、lambda表达式#xff08;匿名函数#xff09;
除了 函数 中介绍的 def语句#xff0c;P…一、概述
Python是一门多范式的编程语言它同时支持过程式、面向对象和函数式的编程范式。因此在Python中提供了很多符合 函数式编程 风格的特性和工具。 二、lambda表达式匿名函数
除了 函数 中介绍的 def语句Python还提供了另外一种定义函数的方法 lambda表达式。
lambda表达式的语法如下
lambda [arguments]: expression与def语句类似lambda表达式创建的函数
也是可调用对象接受0个或多个参数返回一个值也是一等公民first-class)也支持嵌套定义def中的lambda或lambda中的lambda
但是lambda表达式与def语句之间也存在很多显著的差异
差异点函数lambda表达式函数def语句函数体只能是单行表达式expression可以是任意复杂的语句statement函数返回值返回值就是函数体中的表达式的求值结果由函数体中的return语句指定 返回值函数名定义后直接返回函数对象匿名函数定义后自动为函数对象绑定函数名函数定义位置可以在任何允许函数对象出现的位置定义支持即时定义即时调用只能在允许语句出现的位置定义先定义后调用用途多用于一次性使用的简单函数适用于一切函数和类方法
以下是lambda表达式的简单示例
# def语句def func(x, y): return x y # 自动绑定函数名为func
... func
function func at 0xb76eff7cfunc(1, 2) # 先定义后调用
3# lambda表达式lambda x, y: x y # 匿名函数直接返回函数对象
function lambda at 0xb76ef0d4(lambda x, y: x y)(1, 2) # 即时定义即时调用
3f lambda x, y: x y # 手动绑定函数名f(1, 2) # 也可以先定义后调用
3((lambda x: (lambda y: x y))(1))(2) # 嵌套定义的lambda较复杂尽量避免
3三、内建函数filter()、map()、reduce()
1、filter()
函数原型filter(function, iterable)
说明返回一个由iterable中的某些元素组成的列表这些元素使得function返回True。若iterable为字符串或元组则返回字符串或元组否则总是返回列表。如果function为None则默认为恒等函数identity function类似 f(x) x。
示例
# for循环版本res []for x in a1b2c3d4e5f6:
... if x.isalpha():
... res.append(x)
... res
[a, b, c, d, e, f]# filter版本
s a1b2c3d4e5f6filter((lambda x: x.isalpha()), s) # iterable为字符串则返回字符串
abcdeffilter((lambda x: x.isalpha()), tuple(s)) # iterable为元组则返回元组
(a, b, c, d, e, f)filter((lambda x: x.isalpha()), list(s)) # iterable为其他迭代对象则返回列表
[a, b, c, d, e, f]filter(None, list(s)) # function为None则默认为恒等函数
[a, 1, b, 2, c, 3, d, 4, e, 5, f, 6]2、map()
函数原型map(function, iterable, ...)
说明逐个以iterable中的元素为参数调用function并返回结果的列表。如果存在多个iterable则以最长的为准其他不足的补None逐个并行取出元素作为参数调用function如map(function, iter1, iter2)会返回列表[function(iter1[0], iter2[0]), function(iter1[1], iter2[1]), ...]。如果function为None则默认为恒等函数。
示例
# for循环版本res []for x in [1, 2, 3, 4, 5]:
... res.append(x ** 2)
... res
[1, 4, 9, 16, 25]# map版本map((lambda x: x ** 2), [1, 2, 3, 4, 5])
[1, 4, 9, 16, 25]map(None, [1, 2, 3, 4, 5]) # function为None则默认为恒等函数
[1, 2, 3, 4, 5]map((lambda x, y: x y), [1, 2, 3], [4, 5, 6]) # 存在多个iterable则返回[14, 25, 36]
[5, 7, 9]map(None, [1, 2, 3], [4, 5]) # 以最长的iterable为准其他不足的补None
[(1, 4), (2, 5), (3, None)]3、reduce()
函数原型reduce(function, iterable[, initializer])
说明以累加方式逐个取出iterable中的元素作为参数调用具有双参数的function从而最终将iterable简化为一个值如reduce(function, [1, 2, 3])会返回function(function(1, 2), 3)。如果存在initializer则在累加调用中以它作为初始的第一个参数。function必须是可调用对象不能为None。
示例
# for循环版本total 0for x in [1, 2, 3, 4, 5]:
... total x
... total
15# reduce版本reduce((lambda x, y: x y), [1, 2, 3, 4, 5]) # 相当于((((12)3)4)5)
15reduce((lambda x, y: x y), [1, 2, 3, 4, 5], 10) # 带有initializer的reduce相当于(((((101)2)3)4)5)
25sum([1, 2, 3, 4, 5], 10) # 等效于上面的reduce
25四、闭包
闭包closure是一个内嵌函数它能够记住其 外围作用域 中的所有名字即使这个作用域 看起来 已经不在外围。
在以下示例中内嵌函数action就是一个闭包 def maker(N):
... def action(x):
... return x * N
... return action
... mul10 maker(10)mul10(3)
30mul10(5)
50尽管函数调用mul10 maker(10)已经返回并退出了但后续的mul10却能够记住整数10从而计算入参的10倍数。
实际上外围作用域如函数maker对应的代码范围中的所有名字如参数N都作为环境信息被绑定到了action函数上因此每次调用action时都可以访问这些环境信息。特别地可以通过特殊属性func_closure来获取一个函数的自由变量绑定 def maker(N):
... def action(x):
... return x * N
... print(action.func_closure) # 打印出action函数的func_closure属性值
... return action
... N 10print(int N: id %#0x, val %d % (id(N), N)) # N的值为10整数10的地址是0x8e82044
int N: id 0x8e82044, val 10mul10 maker(N) # action.func_closure中含有整数10即自由变量N
(cell at 0x90e96bc: int object at 0x8e82044,)闭包的这种 能够记住环境状态 的特性非常有用Python中有一些其他特性就是借助闭包来实现的比如 装饰器。
五、偏函数应用
1、基本用法
偏函数应用Partial Function Application是一种简化函数调用的方式主要表现为对函数的部分参数进行固化。
Python中的偏函数应用是借助 functools.partial 来完成的。例如有一个专用于生成文章标题的函数title def title(topic, part):
... return topic u part
...如果要为python基础系列的多篇文章生成标题可以有以下两种方式
# 普通版本print title(uPython基础, u开篇)
Python基础开篇print title(uPython基础, u函数)
Python基础函数print title(uPython基础, u函数式编程)
Python基础函数式编程# 偏函数版本from functools import partialpybasic_title partial(title, uPython基础)print pybasic_title(u开篇)
Python基础开篇print pybasic_title(u函数)
Python基础函数print pybasic_title(u函数式编程)
Python基础函数式编程从上面的示例可以看出如果在编码过程中遇到了“多次用相同的参数调用一个函数”的场景就可以考虑使用偏函数来固化这些相同的参数进而简化函数调用。
2、等效实现
1默认参数
在上述示例中如果将函数title的定义改为def title(part, topicuPython基础)也可以达到相同的效果。但是这种方式的不足之处也很明显
需要修改已有函数title的定义默认参数只能有一个固定值定义后即不能更改
相比之下偏函数具有很好的灵活性既不用修改已有函数的定义又可以为函数的参数固化不同的值。
2lambda表达式
使用 lambda表达式 也可以实现类似偏函数的功能并且与默认参数不同的是可以针对不同的参数值定义不同的lambda表达式因为lambda表达式通常是一次性使用的。例如上述示例中的pybasic_title也可以实现为 pybasic_title (lambda part: uPython基础 part)print pybasic_title(u开篇)
Python基础开篇print pybasic_title(u函数)
Python基础函数print pybasic_title(u函数式编程)
Python基础函数式编程但是由于lambda表达式本身的限制参考 『lambda表达式』 一节在具有复杂函数的场景中还得使用偏函数。
3闭包
最后使用 闭包 同样可以等效地实现偏函数的功能并且与lambda表达式不同的是它没有任何限制场景。还是上面的例子 def title(topic):
... def topic_title(part):
... return topic u part
... return topic_title
... pybasic_title title(uPython基础)print pybasic_title(u开篇)
Python基础开篇print pybasic_title(u函数)
Python基础函数print pybasic_title(u函数式编程)
Python基础函数式编程可以看出这个闭包版本的唯一缺点是它需要对函数title进行重新定义与默认参数的情况有些类似。
总而言之如果需要对 已有函数 进行参数固化偏函数是最佳选择。
六、列表解析
这里主要强调两点
列表解析可以用来代替上面提到的一些函数式编程方法列表解析还有一个生成器版本的近亲生成器表达式
1、用列表解析代替filter()和map()
1filter()
列表解析可以完全代替filter()
function不为None时[item for item in iterable if function(item)]等价于filter(function, iterable)function等于None时[item for item in iterable if item]等价于filter(None, iterable)
2map()
在以下情况中列表解析可以代替map()
只有一个iterable时 function不为None[function(item) for item in iterable]等价于map(function, iterable)function等于None[item for item in iterable]等价于map(None, iterable)多个iterable长度相同时 function不为None[function(*args) for args in zip(iter1, iter2, ...)]等价于map(function, iter1, iter2, ...)function等于Nonezip(iter1, iter2, ...)等价于map(None, iter1, iter2, ...)
如果多个iterable具有不同的长度那么列表解析就无法代替map()了。
2、生成器表达式
生成器表达式Generator Expressions与列表解析在语法和功能方面都非常相似。二者的根本差异是生成器表达式返回一个 生成器而列表解析返回一个列表。如下所示
差异点生成器表达式列表解析表示方法(expr for item in iterable if cond_expr)[expr for item in iterable if cond_expr]返回值一个生成器一个列表
与列表解析相比生成器表达式具有 延迟计算lazy evaluation的特点因此在使用内存上更有效。