python匿名函数


上一个章节讲述了自定义函数,而匿名函数则是自定义函数中的特殊情况。而其只需要一行就可以定义,并且还有一个炫酷的名字’lambda’

一、基础

# 定义
lambda arg1,arg2,arg3,...argn:expression

# 举个例子,比如之前定义的my_sum函数
def my_sum(num1, num2):
    return num1+num2
    
# lambda表达式
mysum = lambda x,y: x+y
mysum(2,3)
# 5

# 可以看出lambda其实也是返回的一个函数对象,其与正常方法的用法相同


  • lambda表达式与正常函数的区别
    • lambda是一个表达式,并不是一个语句

      表达式:用一系列"公式"去表达一个东西,比如x + 2、x*2等等
      语句:则一定是完成了某些功能,比如赋值语句x=1 完成了赋值,print语句打印,if 判断等
      
# 由于lambda是一个表达式,所以可以用在一些自定义的常规函数不能用到的地方

# 比如lambda可以用在列表内部
[(lambda x:x+2)(x) for x in range(5)]
#输出:[2, 3, 4, 5, 6]

# 比如作为某些函数的参数
l = [(1,2),(5,7),(3,4)]
l.sort(key = lambda x:x[1])
print(l)
#[(1, 2), (3, 4), (5, 7)]

# 而普通的函数只能通过函数名才能被调用,因此必须先被定义,
# 而lambda作为一个表达式,其可以直接作为表达式返回函数对象
  • lambda的主体是只有一行的简单表达式,并不能扩展成一个多行的代码块

    这样主要是出于设计的考虑,让它和自定义常规函数各司其职:lambda专注简单的任务,自定义常规函数负责更复杂的多行逻辑。

二、为什么使用?

由上可以看出,一个程序完全可以在不使用lambda函数实现其所需要的功能。那我们使用它是为了什么呢?我们可以先大致分析下函数的作用:

  • 减少代码的重复性
  • 模块化代码

第一点,如果程序的不同地方使用到了相同的代码,那么我们就可以把这部分代码提炼成一个函数,为它取个名字,这样我们就可以在不同地方通过这个函数的名字简单的去实现函数中定义的功能

第二点,如果某个功能的实现需要大量非重复的代码去实现,这些代码写在一起就会使程序的可读性异常的低,这个时候,我们就可以把这大量的代码分为多个函数去分别实现,再组装。

但是如果我们需要一个函数,它非常的简短,只需要一行就能完成;同时它在程序中只是别调用一次而已。那么这个时候我们再去使用def去定义一个函数嘛?

而这种情况下,我们的lambda表达式就会凸显出它的优势了!比如上诉的my_sum函数就是一个例子

三、python的函数式编程

函数式编程:指代码中每一块都是不可变的,都是由纯函数的形式组成。这个的纯函数,就是指函数本身相互独立、互不影响,对于相同的输入,总会有相同的输出,没有任何副作用。

# 有影响的函数
l = [1,3,5,7]
def my_list(l):
    for index in range(0,len(l)):
        l[index] += 2
    return l
print(f"第一次调用:{my_list(l)}")
print(f"第二次调用:{my_list(l)}")
# 第一次调用:[3, 5, 7, 9]
# 第二次调用:[5, 7, 9, 11]

# 无影响
l = [1,3,5,7]
def my_list(l):
    my_arr = []
    for index in range(0,len(l)):
        my_arr.append(index)
    return l
print(f"第一次调用:{my_list(l)}")
print(f"第二次调用:{my_list(l)}")
# 第一次调用:[1, 3, 5, 7]
# 第二次调用:[1, 3, 5, 7]

# 第一个就不是纯函数,因为数组的值在每次的调用中会被改变,那么每次得到的结果就是不同的,而第二个则是无影响的

函数编程的优点:主要在于其纯函数和不可变的特性使得程序更加健壮,易于调试和测试;缺点就是限制多且难写,比如scala,不过python也并不是一门函数式的语言,但是其还是提供了一些函数式编程的特性,比如map()、filter()和reduce()这些函数,通常这会与lambda一起使用。
- map(func,iterable)函数,其表示对iterable中的每个元素都调用func函数,最后返回一个新的可遍历的集合

l = [1,2,3,4,5]
new_list = map(lambda x:x+1,l)
print(list(new_list)) #这里使用的是python3所以需要调用下list
# [2, 3, 4, 5, 6]

一些性能测试:

python3 -mtimeit -s'xs=range(500000)' 'map(lambda x: x+1, xs)'
# 1000000 loops, best of 3: 0.21 usec per loop

python3 -mtimeit -s'xs=range(500000)' '[x+1 for x in xs]'
# 10 loops, best of 3: 41.2 msec per loop

python3 -mtimeit -s'xs=range(500000)' 'l = []' 'for i in xs: l.append(i+1)'
# 10 loops, best of 3: 59.9 msec per loop

# 可以看出,map是最快的,因为map()函数直接由C语言写的,运行时不需要通过Python解释器间接调用
  • filter(func,iterable)函数,其与参数那些与map类似,而其表示对iterable 中的每个元素,都使用func判断,并返回True或者False,最后将返回True的元素组成一个新的可遍历的集合
l = [1,2,3,4,5]
new_list = filter(lambda x:x+1,l)
  • reduce(func,iterable)函数,它通常用来对一个集合做一些积累操作。func同样是一个函数对象,规定它有两个参数,表示对iterable 中的每个元素以及上一次调用后的结果,运用func进行计算,一直到最后返回一个单独的数值
from functools import reduce
l = [1,2,3,4,5]
list_sum = reduce(lambda x,y:x+y,l)
print(list_sum)
# 15

你会发现上诉的函数式编程都可以用for循环或者list comprehension实现,那究竟该如何选择使用呢?经过上面的分析其实也可以得出,如果我们对集合元素的操作比较简单,数据量很大的情况下可以优先考虑lambda函数,如果我们数据量不大,元素操作复杂可以优先考虑for循环或者list comprehension实现去实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值