Python lambda表达式(匿名函数)及用法
lambda 表达式(又称匿名函数)是现代编程语言争相引入的一种语法,如果说函数是命名的、方便复用的代码块,那么 lambda 表达式则是功能更灵活的代码块,它可以在程序中被传递和调用。
使用 lambda 表达式代替局部函数
lambda 表达式的语法格式如下:
lambda [parameter_list] : 表达式 从上面的语法格式可以看出 lambda 表达式的几个要点: lambda 表达式必须使用 lambda 关键字定义。 在 lambda 关键字之后、冒号左边的是参数列表,可以没有参数,也可以有多个参数。如果有多个参数,则需要用逗号隔开,冒号右边是该 lambda 表达式的返回值。
[root@kube lambda]# cat demo.py #coding:utf-8 def get_fun(type): if type == 'square': return lambda n: n * n # lambda 代替了函数的重新定义 elif type == 'cube': return lambda n: n * n * n else: return lambda n: n + n a = get_fun('square') b = get_fun('type') print(a(5)) print(b(5)) [root@kube lambda]# py demo.py 25 10 [root@kube lambda]#
总体来说,函数比 lambda 表达式的适应性更强,lambda 表达式只能创建简单的函数对象(它只适合函数体为单行的情形)。但 lambda 表达式依然有如下两个用途:
- 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁。
- 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高了性能。
[root@kube lambda]# cat demo1.py #coding:utf-8 x = map( lambda x: x*x ,range(8)) print('x:',x) print([i for i in x]) [root@kube lambda]# py demo1.py x: <map object at 0x7f8d535a7890> [0, 1, 4, 9, 16, 25, 36, 49] [root@kube lambda]#
正如从上面代码所看到的,内置的 map() 函数的第一个参数需要传入函数,此处传入了函数的简化形式:lambda 表达式,这样程序更加简洁,而且性能更好。
节所介绍的 lambda 表达式是 Python 编程的核心机制之一。Python 语言既支持面向过程编程,也支持面向对象编程。而 lambda 表达式是 Python 面向过程编程的语法基础,因此读者必须引起重视。
Python eval()和exec()函数详解
eval() 和 exec() 函数都属于 Python 的内置函数,由于这两个函数在功能和用法方面都有相似之处,所以将它们放到一节进行介绍。
eval() 和 exec() 函数的功能是相似的,都可以执行一个字符串形式的 Python 代码(代码以字符串的形式提供),相当于一个 Python 的解释器。二者不同之处在于,eval() 执行完要返回结果,而 exec() 执行完不返回结果(文章后续会给出详细示例)。
eval()和exec()的用法 eval() 函数的语法格式为: eval(expression, globals=None, locals=None, /) 而 exec() 函数的语法格式如下: exec(expression globals=None, locals=None, /)
可以看到,二者的语法格式除了函数名,其他都相同,其中各个参数的具体含义如下:
- expression:这个参数是一个字符串,代表要执行的语句 。该语句受后面两个字典类型参数 globals 和 locals 的限制,只有在 globals 字典和 locals 字典作用域内的函数和变量才能被执行。
- globals:这个参数管控的是一个全局的命名空间,即 expression 可以使用全局命名空间中的函数。如果只是提供了 globals 参数,而没有提供自定义的 __builtins__,则系统会将当前环境中的 __builtins__ 复制到自己提供的 globals 中,然后才会进行计算;如果连 globals 这个参数都没有被提供,则使用 Python 的全局命名空间。
- locals:这个参数管控的是一个局部的命名空间,和 globals 类似,当它和 globals 中有重复或冲突时,以 locals 的为准。如果 locals 没有被提供,则默认为 globals。
注意,__builtins__ 是 Python 的内建模块,平时使用的 int、str、abs 都在这个模块中。通过 print(dic["__builtins__"]) 语句可以查看 __builtins__ 所对应的 value。
实例:
[root@kube lambda]# cat eval.py x = 10 def func(): y = 20 a = eval('x + y') print('a: ', a) b = eval('x + y', {'x': 1, 'y': 2}) print('b: ', b) c = eval('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) print('c: ', c) d = eval('print(x, y)') print('d: ', d) func() [root@kube lambda]# py eval.py a: 30 b: 3 c: 4 10 20 d: None [root@kube lambda]#
对输出结果的解释:
对于变量a,eval函数的globals和locals参数都被忽略了,因此变量x和变量y都取得的是eval函数被调用环境下的作用域中的变量值,即:x = 10, y = 20,a = x + y = 30
对于变量b,eval函数只提供了globals参数而忽略了locals参数,因此locals会取globals参数的值,即:x = 1, y = 2,b = x + y = 3
对于变量c,eval函数的globals参数和locals都被提供了,那么eval函数会先从全部作用域globals中找到变量x, 从局部作用域locals中找到变量y,即:x = 1, y = 3, c = x + y = 4
对于变量d,因为print()函数不是一个计算表达式,没有计算结果,因此返回值为None
我们把实例1中的eval函数换成exec函数试试:
[root@kube lambda]# cat eval.py x = 10 def func(): y = 20 a = exec('x + y') print('a: ', a) b = exec('x + y', {'x': 1, 'y': 2}) print('b: ', b) c = exec('x + y', {'x': 1, 'y': 2}, {'y': 3, 'z': 4}) print('c: ', c) d = exec('print(x, y)') print('d: ', d) func() [root@kube lambda]# py eval.py a: None b: None c: None 10 20 #只是执行 print(x,y) 返回值还是 None d: None [root@kube lambda]#
因为我们说过了,exec函数的返回值永远为None。
Python函数式编程(map()、filter()和reduce())详解
所谓函数式编程,是指代码中每一块都是不可变的,都由纯函数的形式组成。这里的纯函数,是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出。不改变原始数据
Python map()函数
map() 函数的基本语法格式如下: map(function, iterable) 其中,function 参数表示要传入一个函数,其可以是内置函数、自定义函数或者 lambda 匿名函数;iterable 表示一个或多个可迭代对象,可以是列表、字符串等。 map() 函数的功能是对可迭代对象中的每个元素,都调用指定的函数,并返回一个 map 对象。 注意,该函数返回的是一个 map 对象,不能直接输出,可以通过 for 循环或者 list() 函数来显示。
[root@kube lambda]# cat demo4.py #coding:utf-8 lt = [1,2,3,'a','b'] new_list = map(lambda x: x*2,lt) print(new_list) print(type(new_list)) print(list(new_list)) [root@kube lambda]# py demo4.py <map object at 0x7f98bb95c2d0> <class 'map'> [2, 4, 6, 'aa', 'bb'] [root@kube lambda]#
[root@kube lambda]# cat demo5.py listDemo1 = [1, 2, 3, 4, 5] listDemo2 = [3, 4, 5, 6, 7] new_list = map(lambda x,y: x + y, listDemo1,listDemo2) print(list(new_list)) [root@kube lambda]# py demo5.py [4, 6, 8, 10, 12] [root@kube lambda]#
Python filter()函数
filter()函数的基本语法格式如下:
filter(function, iterable)
此格式中,funcition 参数表示要传入一个函数,iterable 表示一个可迭代对象。
filter() 函数的功能是对 iterable 中的每个元素,都使用 function 函数判断,并返回 True 或者 False,最后将返回 True 的元素组成一个新的可遍历的集合。
[root@kube lambda]# cat demo6.py #coding:utf-8 lt = [1,2,3,4,5] new_lt = filter(lambda x: x % 2 == 0 , lt) print(type(new_lt)) print(list(new_lt)) [root@kube lambda]# py demo6.py <class 'filter'> [2, 4] [root@kube lambda]#
Python reduce()函数
reduce() 函数通常用来对一个集合做一些累积操作,其基本语法格式为: reduce(function, iterable) 其中,function 规定必须是一个包含 2 个参数的函数;iterable 表示可迭代对象。 注意,由于 reduce() 函数在 Python 3.x 中已经被移除,放入了 functools 模块,因此在使用该函数之前,需先导入 functools 模块。
[root@kube lambda]# cat demo7.py #coding:utf-8 import functools lt = [1,2,3,4,5,6] product = functools.reduce(lambda x,y: x * y,lt) print(product) [root@kube lambda]# py demo7.py 720 [root@kube lambda]#
Python 3函数注解:为函数提供类型提示信息
数注解是 Python 3 最独特的功能之一,关于它的介绍,官方文档是这么说的,“函数注解是关于用户自定义函数使用类型的完全可选的元信息”。也就是说,官方将函数注解的用途归结为:为函数中的形参和返回值提供类型提示信息。
[root@kube lambda]# cat demo8.py #coding:utf-8 def square(num: '一个数字')->'返回这个数的平方': return num ** 2 print(square(200)) print(square.__annotations__) [root@kube lambda]# py demo8.py 40000 {'num': '一个数字', 'return': '返回这个数的平方'} [root@kube lambda]#
如上所示,给函数中的参数做注解的方法是在形参后添加冒号“:”,后接需添加的注解(可以是类(如 str、int 等),也可以是字符串或者表示式);给返回值做注解的方法是将注解添加到 def 语句结尾的冒号和 -> 之间。
[root@kube lambda]# cat demo10.py #coding:utf-8 def solve(arr,target): b = sorted(arr) for i in b: if i * i > target: return i return -1 print(solve([61, 2, 7, 4, 5, 8], 70)) print(solve([10, 2, 3, 7, 5, 6], 9)) print(solve([10, 20, 3, 4, 5, 6], 0)) print(solve([10, 8, 3, 4, 5, 6], 200)) [root@kube lambda]# py demo10.py 61 5 3 -1 [root@kube lambda]#
首先,大家在编程过程中,一定要围绕一个中心思想:不写重复性的代码。因为,重复代码往往是可以通过使用条件、循环、构造函数和类(后续章节会做详细介绍)来解决的
还要学会刻意地减少代码的迭代层数,尽可能让 Python 代码扁平化。
另外,在使用函数时,函数的粒度应该尽可能细,不要让一个函数做太多的事情。往往一个复杂的函数,我们要尽可能地把它拆分成几个功能简单的函数,然后合并起来。