Python学习笔记:匿名函数与lambda表达式

一、Python函数

Python 中使用 def + 函数名 + 参数 的方式定义函数,即:

# 函数定义
def function_name(parameters): # 形参
    print("hello" + parameters)
   
# 函数调用
function_name("Hider") # 实参

将通过 def 所定义的函数称为“有名函数”。

匿名函数则是没有明确的定义函数名。

二、匿名函数

lambda表达式:通常是在需要一个函数,但又不想去命名一个函数的时候使用,即匿名函数。

匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数。

匿名函数不需要显示地定义函数名,使用 lambda + 参数 + 表达式 的方式,即:

lambda [arg1 [,arg2, ...argN]]: expression

可以传入多个参数,但只能有一个表达式。

# 实际对比案例
# def定义方式
def fun(x, y):
    return x*y

# 调用
fun(2, 3)
6

# 匿名函数
func = lambda x,y : x*y
func(2, 3)
6
# 定义def
def calc(x,y):
    if x > y:
        return x*y
    else:
        return x/y
# 执行
calc(2,5) # 0.4
calc(5,2) # 10

# 三元运算换成匿名函数
calc = lambda x, y : x*y if x > y else x/y
calc(2,5) # 0.4
calc(5,2) # 10

匿名函数的优势:

  1. 不需要取名称
  2. 可以直接使用,不用提前定义,方便修改
  3. 语法结构简单

三、应用

1.应用在函数式编程中

Python提供了很多函数式编程的特性。

map、reduce、filter、sorted等函数都支持函数作为参数,lambda函数就可以应用在函数式编程中。

  • map函数

map函数接收两个参数,一个是函数,一个是iterator(可迭代对象),map将传入的函数依次作用到序列的每个元素,并把结果作为新的iterator返回。

# 返回n*n列表
# 方法1
list1 = [1,2,3,4,5,6,7,8,9,10]
for i in range(len(list1)):
    list1[i] = list1[i]**2
print(list1)
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 方法2
list2 = [1,2,3,4,5,6,7,8,9,10]
for i, val in enumerate(list2):
    list2[i] = val * val
print(list2)
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 方法3:高级用法
list3 = [1,2,3,4,5,6,7,8,9,10]
print(list(map(lambda x:x**2, list3)))
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
# 针对列表转换为字典
number_list = [100, 77, 69, 31, 44, 56]
num_sum = list(map(lambda x:{str(x):x}, number_list))
print(num_sum)
  • reduce函数

reduce把一个函数作用在一个序列上,接收2个参数,reduce把结果继续和序列的下一个元素做累积计算。

# 接收一个list并利用reduce()求积
from functools import reduce
list4 = [1,2,3,4,5,6,7,8,9,10]
reduce(lambda x,y:x*y, list4) 
# 1*2*3*4*5*6*7*8*9*10 = 3628800
  • filter函数

filter函数也接收一个函数和一个序列,和map函数不同的是,filter函数把传入的函数依次作用于每个元素,然后根据返回值是否为True,决定保留还是丢弃该元素。

# 删除偶数 只保留奇数
list5 = [1,2,3,4,5,6,7,8,9,10]
list(filter(lambda x:x%2==1, list5))
# [1, 3, 5, 7, 9]
# 取反操作
x = 1563
str(x)[::-1] # '3651'

# 回数是指从左向右读和从右向左读都是一样的数,例如12321,909
# 利用filter筛选出回数
list6 = list(range(200))
print(list(filter(lambda x:int(str(x)) == int(str(x)[::-1]), list6)))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]
  • sorted函数

sorted函数使用格式:sorted(iterable, /, *, key=None, reverse=False)

接收一个key函数实现对可迭代对象的自定义排序。

可迭代对象:列表、字符串、元组、集合、字典。

reverse为排序方向,默认从小到大,True为逆向。

例如:

# 将列表中的元素按照绝对值大小进行升序排列
list1 = [3,5,-4,-1,0,-2,-6]
sorted(list1, key=lambda x:abs(x))
# [0, -1, -2, 3, -4, 5, -6]

# def
def get_abs(x):
    return abs(x)
sorted(list1, key=get_abs)
# [0, -1, -2, 3, -4, 5, -6]
# 以首字母排序
li = ['bad', 'about', 'Zoo', 'Credit']
sorted(li, key=lambda x:x[0])
# ['Credit', 'Zoo', 'about', 'bad']
"""
对字符串排序,是按照ASCII的大小比较的,由于'Z' < 'a',结果,大写字母Z会排在小写字母a的前面。
"""
# 学生姓名 + 成绩
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
# 按姓名排序
sorted(L, key=lambda x:x[0])
# [('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]
# 按成绩从高到低
sorted(L, key=lambda x:x[1], reverse=True)
# [('Adam', 92), ('Lisa', 88), ('Bob', 75), ('Bart', 66)]
# 针对字典操作
member_list = [
    {"name": "风清扬", "age": 99, "power": 10000},
    {"name": "无崖子", "age": 89, "power": 9000},
    {"name": "王重阳", "age": 120, "power": 8000}
]
new_list = sorted(member_list, key=lambda x:x["power"])
print(new_list)

2.应用在闭包中

# 定义
def get_y(a,b):
    return lambda x:a*x+b
# 调用
y1 = get_y(1,1)
y1(1) # 2

# def
def get_y(a,b):
    def func(x):
        return a*x+b
    return func
y1 = get_y(1,1)
y1(1) # 2

Python之禅中有这么一句话:Explicit is better than implicit(明了胜于晦涩),哪种方式更清晰就用哪一种方式,不要盲目的都使用lambda表达式。

参考链接1:一文搞懂Python匿名函数

参考链接2:Python函数学习——匿名函数

参考链接3:Python匿名函数lambda的使用