一、Lambda匿名函数
Python使用lambda关键字定义匿名函数(又称Lambda函数)。匿名函数并非没有名称,而是将其作为函数对象返回,语法格式如下:
<函数名> = lambda <参数列表>:<表达式>
Lambda函数等价于常规函数定义:
def <函数名>(<参数列表>):
return <表达式>
Lambda函数适用于定义简单的、可在一行内表示的短小函数,返回一个函数对象。
示例:按文件扩展名分组
files = ["报告.doc", "数据.xls", "图片.png"]
grouped = sorted(files, key=lambda x: x.split('.')[-1])
print(grouped) # 输出: ['报告.doc', '数据.xls', '图片.png']
# 等价普通函数
def get_ext(filename):
return filename.split('.')[-1]
注意:
1. Lambda的限制:
o 只能包含单个表达式,不能包含语句(如if-else三元表达式允许,但多分支if不行)
o 不能包含类型注解
o 没有函数名(__name__属性为<lambda>)
2. 适用场景:
o 作为高阶函数的参数(如sorted(), filter(), map())
o 需要一次性使用的简单函数
o 闭包和函数工厂
3. 与常规函数对比:
# Lambda表达式
square = lambda x: x ** 2
# 常规函数
def square(x):
return x ** 2
4. 作用域规则:
o Lambda函数遵循与常规函数相同的作用域规则
o 可以访问定义时的全局变量和闭包变量
o 需要修改全局变量时同样需使用global声明
二、递归函数
1. 递归的定义
递归是函数调用自身的一种编程技巧,包含两个关键特征:
(1). 基线条件:一个或多个不需要递归的直接解决方案(递归终止条件)
(2). 递归链:所有递归调用最终必须收敛到基线条件
2. 递归的执行机制
每次递归调用都会创建新的函数栈帧,包含:
· 独立的局部变量副本(包括参数)
· 独立的执行上下文
当达到基线条件时,递归开始逐层返回:
示例:文件夹扫描
import os
def scan_folder(path, indent=0):
"""递归扫描文件夹结构"""
print(" " * indent + f" {os.path.basename(path)}")
for item in os.listdir(path):
item_path = os.path.join(path, item)
if os.path.isdir(item_path):
scan_folder(item_path, indent + 4) # 递归调用
else:
print(" " * (indent + 4) + f" {item}")
scan_folder("/projects")
注意:
(1). 递归深度限制:
import sys
print(sys.getrecursionlimit()) # 默认1000
sys.setrecursionlimit(1500) # 修改递归深度
(2). 递归优化技术:
o 记忆化:缓存计算结果避免重复计算
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
o 尾递归优化(Python虽不支持,但可模拟):
def factorial(n, acc=1):
if n == 0:
return acc
return factorial(n-1, acc*n)
3. 作用域特性:
o 每次递归调用创建新的局部作用域
o 递归函数中的变量相互隔离
o 修改全局变量仍需global声明
4. 递归使用原则:
o 确保存在有效的基线条件
o 每次递归应向基线条件收敛
o 避免递归深度过大(>1000层)
o 考虑迭代替代方案(特别是线性递归)
5. 常见递归模式:
# 分治递归
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr)//2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
# 树形结构递归
class Node:
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def tree_depth(node):
if not node:
return 0
return max(tree_depth(node.left), tree_depth(node.right)) + 1