zzzzy09

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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 代码扁平化。
另外,在使用函数时,函数的粒度应该尽可能细,不要让一个函数做太多的事情。往往一个复杂的函数,我们要尽可能地把它拆分成几个功能简单的函数,然后合并起来。

 

posted on 2019-10-09 17:47  zzzzy09  阅读(316)  评论(0编辑  收藏  举报