摘要:你已经掌握了如何创建和使用函数,但Python函数的潜力远不止于此。本文将带你学习三个函数式编程的“进阶神技”:Lambda表达式、高阶函数和装饰器。它们能让你的代码变得难以置信地简洁、优雅和强大。学完本篇,你将学会用更“Pythonic”的方式思考和解决问题,代码水平提升一个台阶。

前言:从“会用”到“巧用”

如果说上一篇是让你“会用”函数,那么本篇就是教你如何“巧用”函数。Python吸收了大量函数式编程的思想,允许你像操作数字和列表一样去操作函数本身——将函数作为参数传递,或者让一个函数返回另一个函数。

理解并掌握这些技巧,是区分Python初学者和有经验开发者的重要分水岭。准备好,我们将要学习一些能让你的代码“魔力十足”的技巧。


一、Lambda表达式:一次性的“便签”函数

有时候,你需要一个非常简单的函数,只用一次,为此专门def一个完整的函数显得有点“小题大做”。Lambda表达式就是为此而生的匿名、单行函数

它就像一张“便签”,当你需要快速记录并使用一个简单逻辑时,随手写下,用完即扔。

  • 语法lambda 参数列表: 表达式

这个表达式的计算结果就是Lambda函数的返回值。

让我们对比一下deflambda

# --- 使用 def ---
def square(x):
    return x * x

print(square(5)) # 输出: 25

# --- 使用 lambda ---
square_lambda = lambda x: x * x

print(square_lambda(5)) # 输出: 25

Lambda的核心优势在于它无需命名,可以直接用在需要函数作为参数的地方,让代码更紧凑。


二、高阶函数:操作函数的函数

一个函数如果可以接收另一个函数作为参数,或者把函数作为返回值,那它就是一个高阶函数。这就像一个“经理”函数,它不亲自干活,而是指挥其他“员工”函数去完成任务。

Python内置了许多有用的高阶函数,最常见的有sorted(), map(), filter()

2.1 sorted():自定义排序规则

sorted()函数可以对任何可迭代对象进行排序。它有一个非常强大的key参数,可以接收一个函数,用来指定排序的规则。

# 假设有一个学生列表,每个学生是一个字典
students = [
    {'name': 'Alice', 'age': 25},
    {'name': 'Bob', 'age': 20},
    {'name': 'Charlie', 'age': 23}
]

# 按年龄排序
# key接收一个函数,这个函数会作用于列表的每一个元素
# lambda student: student['age'] 的作用就是返回每个学生的年龄
sorted_by_age = sorted(students, key=lambda student: student['age'])

print(sorted_by_age)
# 输出: [{'name': 'Bob', 'age': 20}, {'name': 'Charlie', 'age': 23}, {'name': 'Alice', 'age': 25}]

看到lambda的威力了吗?我们用一行代码就定义了一个简洁的排序规则。

2.2 map():批量“加工”数据

map(function, iterable)会将一个函数应用到可迭代对象的每一个元素上,并返回一个包含所有结果的迭代器。

numbers = [1, 2, 3, 4, 5]

# 将列表中每个数都平方
# map会把lambda x: x * x这个函数,依次作用于numbers中的1, 2, 3, 4, 5
squared_numbers = map(lambda x: x * x, numbers)

print(list(squared_numbers)) # 输出: [1, 4, 9, 16, 25]

2.3 filter():按需“筛选”数据

filter(function, iterable)会根据函数的返回值(TrueFalse)来过滤可迭代对象中的元素,只保留那些让函数返回True的元素。

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 筛选出所有的偶数
# filter会把lambda x: x % 2 == 0作用于每个数字,只留下结果为True的
even_numbers = filter(lambda x: x % 2 == 0, numbers)

print(list(even_numbers)) # 输出: [2, 4, 6, 8, 10]

三、装饰器(@):给函数穿上“功能外套”

装饰器是Python中一个相对高级但 cực kỳ powerful 的概念。它允许你在不修改原函数代码的情况下,为该函数增加额外的功能

它就像一个“汉堡包装纸”,汉堡本身(原函数)没变,但包装纸(装饰器)给它增加了品牌信息、防油等额外功能。

核心思想:装饰器本质上是一个接收函数作为参数并返回一个新函数的高阶函数。

让我们通过一个场景来理解它:假设我们想计算某个函数的运行时间。

import time

# 1. 首先,创建一个装饰器函数
def timer_decorator(func):
    # 定义一个内部函数(包装器),它会接收原函数的所有参数
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs) # 在这里执行原函数
        end_time = time.time()
        print(f"函数 '{func.__name__}' 运行耗时: {end_time - start_time:.4f} 秒")
        return result
    return wrapper # 装饰器返回这个包装好的新函数

# 2. 使用 @ 语法糖来应用装饰器
@timer_decorator
def slow_function(delay_time):
    """一个需要执行一段时间的函数"""
    print("函数开始执行...")
    time.sleep(delay_time)
    print("函数执行完毕。")
    return "任务完成"

# 3. 正常调用原函数
result = slow_function(2)
print(f"函数返回值: {result}")

输出:

函数开始执行...
函数执行完毕。
函数 'slow_function' 运行耗时: 2.0013 秒
函数返回值: 任务完成

发生了什么?

  • @timer_decorator 这行代码,等价于在函数定义之后写了一句 slow_function = timer_decorator(slow_function)
  • 它把我们的slow_function函数作为“原材料”传递给了timer_decorator
  • timer_decorator返回了一个新的函数wrapper,并重新赋值给了slow_function这个名字。
  • 所以,当我们调用slow_function(2)时,实际上执行的是那个被“包装”过的wrapper(2)函数。wrapper在内部执行了计时,并调用了我们最初的slow_function

装饰器在Web框架(如Flask, Django)中用于路由和权限验证,在日志记录、性能测试等领域有广泛应用。


总结

在本篇中,我们学习了三个能够显著提升你代码质量的函数式编程工具:

  • Lambda表达式:用于创建临时的、单行的匿名函数,是高阶函数的最佳伴侣。
  • 高阶函数 (sorted, map, filter):通过接收函数作为参数,实现了对通用逻辑的抽象,让代码更具表现力。
  • 装饰器 (@):遵循“开放封闭原则”,在不修改源码的情况下为函数附加新功能,是代码解耦和复用的利器。

现在,你不仅能写出能工作的代码,更能写出简洁、优雅、易于扩展的Pythonic代码。

预告:【Python精讲 #08】面向对象(OOP)一篇通:类、继承、封装与多态核心精讲

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐