目录
[1. 为什么函数也是对象](#1. 为什么函数也是对象)
[2. 函数添加自定义属性](#2. 函数添加自定义属性)
[3. 函数赋值给变量](#3. 函数赋值给变量)
[4. 函数作为参数](#4. 函数作为参数)
[5. 函数作为返回值](#5. 函数作为返回值)
[1. 多返回值](#1. 多返回值)
[2. 参数打包](#2. 参数打包)
[2.1 位置参数打包](#2.1 位置参数打包)
[2.2 关键字参数打包](#2.2 关键字参数打包)
[3. 参数解包](#3. 参数解包)
[4. 参数传递机制](#4. 参数传递机制)
[1. 为什么需要高阶函数](#1. 为什么需要高阶函数)
[2. 高阶函数案例](#2. 高阶函数案例)
[四、Lambda 表达式](#四、Lambda 表达式)
[1. Lambda 语法](#1. Lambda 语法)
[2. Lambda 应用场景](#2. Lambda 应用场景)
[3. Lambda 注意事项](#3. Lambda 注意事项)
[五、Python 常用高阶函数](#五、Python 常用高阶函数)
[1. map()](#1. map())
[2. filter()](#2. filter())
[3. sorted()](#3. sorted())
[4. reduce()](#4. reduce())
[1. 为什么需要条件表达式](#1. 为什么需要条件表达式)
[2. 语法结构](#2. 语法结构)
[3. 应用场景示例](#3. 应用场景示例)
[4. 什么时候不该使用](#4. 什么时候不该使用)
[1. 为什么需要推导式](#1. 为什么需要推导式)
[2. 基本语法](#2. 基本语法)
[3. 条件推导式](#3. 条件推导式)
[4. 多层推导式](#4. 多层推导式)
一、重新认识函数
在基础语法阶段,我们通常将函数视为一段封装好的、用于执行特定任务的代码块。我们定义它,然后通过小括号调用它。这是一种典型的面向过程的思维方式
然而,要真正解锁 Python 的高级特性(如闭包、装饰器、函数式编程等),我们必须打破这种传统的认知。在 Python 的哲学里,函数不仅是代码块,更是活生生的对象
1. 为什么函数也是对象
在 Python 的世界遵循一切皆对象的核心法则。整数、字符串、列表是对象,我们自定义的类和实例是对象,连函数本身也是对象
使用 def 关键字定义一个函数时,Python 解释器在底层实际上做了两件事:
-
在堆内存中创建了一个类型为 function 的对象实体,里面封装了函数的执行代码、命名空间等数据
-
在当前的命名空间中创建了一个变量(即你的函数名),并将这个变量作为指针,指向刚刚创建的函数对象

我们可以通过内置函数 type() 和 id() 来直接证实这一物理事实:
python
def greet(name):
return f"Hello, {name}!"
# 1. 验证函数的类型
print(type(greet)) # 输出:<class 'function'>
# 2. 验证函数的内存地址
print(id(greet)) # 输出:一串内存地址数字

既然函数是 function 类的对象,那么它就天然具备了对象的所有特性:可以被赋值给变量、可以作为容器元素的成员、拥有自己的属性、作为参数传递,也可以作为返回值返回
2. 函数添加自定义属性
既然函数是对象,它就可以像普通对象一样,在运行期间动态地挂载自定义属性。这一特性在编写某些需要记忆状态的特殊函数时非常有用(例如实现轻量级的计数器,而无需动用全局变量或类)
python
def regular_service():
print("正在执行核心业务逻辑...")
# 动态累加函数自身的属性
regular_service.call_count += 1
# 在函数对象上初始化一个自定义属性
regular_service.call_count = 0
# 连续调用
regular_service()
regular_service()
# 外部直接读取函数对象的属性
print(f"该函数一共被调用了 {regular_service.call_count} 次。") # 输出:2


3. 函数赋值给变量
在 Python 中,函数名本质上就是一个普通的变量名。我们可以将一个函数名赋值给另一个新变量,这仅仅意味着让新变量也指向同一个函数对象
python
def cal_tax(income):
return income * 0.2
# 1. 将函数对象赋值给另一个变量(注意:不要加小括号,加小括号表示调用函数)
tax_p = cal_tax
# 2. 验证两者的内存地址完全一致
print(id(cal_tax) == id(tax_p)) # 输出:True
# 3. 通过新变量调用函数
result = tax_p(5000)
print(f"应缴税额:{result}") # 输出:1000.0


4. 函数作为参数
函数能够作为参数传递给另一个函数,是现代软件工程解耦的核心手段之一。它允许我们将执行逻辑像普通数据一样在程序中自由传递
python
def stars(text):
return f"*** {text} ***"
def brackets(text):
return f"[[ {text} ]]"
# 渲染函数:接收一个文本和一个"格式化函数对象"作为参数
def render_engine(raw_text, formatter_func):
# 面向行为编程:直接调用传入的函数对象
processed_text = formatter_func(raw_text)
print(f"渲染:{processed_text}")
# 传入不同的行为对象,得到不同的输出结果
render_engine("Core Data", stars) # 输出:*** Core Data ***
render_engine("Core Data", brackets) # 输出:[[ Core Data ]]

5. 函数作为返回值
一个函数不仅可以接收数据和行为,还可以在其内部动态生成并返回一个全新的函数对象
python
def get_multiplier(factor):
"""根据传入的因子,动态生成并返回一个定制的乘法函数"""
# 在内部定义一个局部函数
def multiplier(number):
return number * factor
# 将这个内部函数对象作为成果返回出去
return multiplier
# 生成一个"翻三倍"的专属函数
triple_func = get_multiplier(3)
print(triple_func(10)) # 输出:30
# 生成一个"翻十倍"的专属函数
decaple_func = get_multiplier(10)
print(decaple_func(10)) # 输出:100

二、函数参数进阶
Python 为函数提供了灵活多变的参数机制,使其能够在系统内高效运作
1. 多返回值
在很多传统的编程语言中,一个函数通常只能返回一个数据。如果需要返回多个数据,往往必须将其打包成一个复杂的结构体或对象。而 Python 允许非常直观的多返回值写法:
python
def analyze(scores):
highest = max(scores)
lowest = min(scores)
average = sum(scores) / len(scores)
# 返回了三个数值
return highest, lowest, average
result = analyze([88, 95, 70, 64, 100])
print(type(result)) # 输出:<class 'tuple'>
print(result) # 输出:(100, 64, 83.4)

底层机制:
Python 在底层根本不支持真正的多返回值 。上述代码中,return highest, lowest, average 被隐式地打包成了一个单一的元组(Tuple)对象
也就是说,函数自始至终只返回了一个对象。而外部能够通过 max_v, min_v, avg_v = analyze(...) 进行接收,靠的是 Python 自动触发的元组拆包机制
2. 参数打包
在工程设计中,我们经常无法预知一个函数未来会接收到多少个参数。为了应对这种不确定性,Python 提供了参数打包机制
2.1 位置参数打包
当你在函数的形参(Parameter)前加上一个星号 * 时,这意味着该形参将接收所有未被显式捕获的位置参数,并在底层将其自动打包成一个元组
python
def make_pizza(size, *toppings):
print(f"正在制作一个 {size} 英寸的披萨。")
print(f"添加的配料:{toppings},其类型是:{type(toppings)}")
# 调用时,多出来的配料参数被自动收拢到一个元组中
make_pizza(12, "香肠", "蘑菇", "青椒")
# 输出:
# 正在制作一个 12 英寸的披萨。
# 添加的配料元组:('香肠', '蘑菇', '青椒'),其类型是:<class 'tuple'>

2.2 关键字参数打包
当你在形参前加上两个星号时,这意味着该形参将接收所有未被显式捕获的关键字参数,并在底层将其自动打包成一个字典
python
def build_profile(first, last, **user_info):
profile = {"first_name": first, "last_name": last}
# 直接将打包好的字典合并进来
profile.update(user_info)
return profile
user_data = build_profile("Albert", "Einstein", field="Physics", Nobel=True)
print(user_data)
# 输出:{'first_name': 'Albert', 'last_name': 'Einstein', 'field': 'Physics', 'Nobel': True}

3. 参数解包
参数解包是打包的逆向操作。当你手中已经拥有一个容器数据(如列表、元组或字典),而你需要将它们逐一传递给一个普通函数时,可以使用解包操作
-
* 作用于列表/元组时,会将其拆散为独立的位置参数
-
作用于字典时,会将其拆散为独立的关键字参数对
python
def create_sandbox(ip, port, debug_mode):
print(f"服务器配置:IP={ip}, Port={port}, Debug={debug_mode}")
# 1. 列表位置参数解包
network_config = ["192.168.1.100", 8080, True]
create_sandbox(*network_config) # 等价于 create_sandbox("192.168.1.100", 8080, True)
# 2. 字典关键字参数解包
kv_config = {"ip": "10.0.0.1", "port": 443, "debug_mode": False}
create_sandbox(**kv_config)
# 等价于 create_sandbox(ip="10.0.0.1", port=443, debug_mode=False)

4. 参数传递机制
Python 对于函数参数的定义是赋值传递 或对象引用传递
其核心逻辑为:向函数传递一个实参时,函数内部的形参变量仅仅是拷贝了该实参的内存地址指针(即两者共享同一个堆内存对象) 。至于函数内部的操作是否会影响到函数外部,完全取决于传入对象的可变性
python
def modify_data(num_param, list_param):
num_param += 10 # 操作不可变对象(int)
list_param.append(999) # 操作可变对象(list)
print(f"函数内部:num={num_param}, lst={list_param}")
outer_num = 5
outer_lst = [1, 2]
modify_data(outer_num, outer_lst)
# 输出:函数内部:num=15, lst=[1, 2, 999]
print(f"函数外部:outer_num={outer_num}, outer_lst={outer_lst}")
# 输出:函数外部:outer_num=5, outer_lst=[1, 2, 999]

-
针对不可变对象:传入函数时,形参 num_param 指向 5。当执行 num_param += 10 时,由于整数不可变,Python 只好在堆内存中新开辟空间计算出 15,并将 num_param 指向这个新位置。此时外部的 outer_num 依然指向原来的 5,不受任何影响
-
针对可变对象:传入函数时,list_param 共享了列表的物理地址。执行 list_param.append(999) 时,由于列表支持就地修改,Python 直接在原物理空间追加了元素。这就导致函数外部的 outer_lst 同步发生了改变
永远不要使用可变类型(如空列表、空字典)作为函数的默认参数(如 def func(data=\[\]))。由于默认参数在函数加载时有且仅被初始化一次,所有的调用都将共享这一个同一个物理列表,这极易引发灾难性的逻辑污染
三、高阶函数
高阶函数的定义非常简单。一个函数只要满足以下两个条件中的任意一个,它就被称为高阶函数:
-
接受一个或多个函数作为参数传入
-
将一个函数作为执行结果返回
1. 为什么需要高阶函数
我们的代码往往将控制流与具体算法死死地捆绑在一起
例如,你需要开发一个包含多个核心业务的方法链,架构师要求:在执行每一个业务方法前,必须记录一条安全审计日志,并测量该业务的执行耗时
如果没有高阶函数,你只能在每个独立的业务函数内部,重复地复制、粘贴日志记录与耗时测量的代码。这不仅造成了严重的冗余,也使得核心业务代码变得极难阅读。
高阶函数的工程价值在于:它允许我们将基础设施逻辑(如日志、安全校验、耗时统计、异常重试)抽象并封装在高阶函数内部,而将具体的业务逻辑作为函数对象投递进来。 从而实现横切关注点的完美分离
2. 高阶函数案例
下面通过一个 "业务耗时与审计监测网关" 案例,展示高阶函数如何对逻辑进行解密和组合
python
import time
# 1. 业务逻辑层(不掺杂任何监控代码)
def fetch_user_data(user_id):
"""模拟从数据库拉取数据的耗时操作"""
time.sleep(0.3) # 模拟网络延迟
return {"user_id": user_id, "role": "VIP", "status": "Active"}
def generate_report(data_dict):
"""模拟复杂的报表渲染计算"""
time.sleep(0.5) # 模拟CPU密集型计算
return f"【报表资产】身份验证成功,用户角色为 {data_dict['role']}"
# 2. 基础设施层(接受函数作为参数)
def execution_monitor(target_func, *args, **kwargs):
"""
高阶监视器。
负责统一接管控制流,拦截目标函数的执行,注入审计与计时逻辑。
"""
print(f"[审计系统] :检测到正在尝试调用函数 -> '{target_func.__name__}'")
start_time = time.time()
# 多态地执行传入的行为对象,并利用参数解包投递业务数据
result = target_func(*args, **kwargs)
end_time = time.time()
elapsed = round((end_time - start_time) * 1000, 2)
print(f"[审计系统] 函数 '{target_func.__name__}' 物理耗时: {elapsed} 毫秒。\n")
# 将业务函数的正果安全交付出去
return result
运行验证:
python
# 传统的调用方式需要将监控代码塞进函数内。
# 现在,我们直接将业务行为与数据一并投递给高阶监视器:
# 监控业务一:拉取数据
user_info = execution_monitor(fetch_user_data, user_id=9527)
# 监控业务二:生成报表
report_text = execution_monitor(generate_report, user_info)
print(f"最终流水线输出结果:{report_text}")
结果输出:

通过这个案例可以清晰地看到,fetch_user_data 和 generate_report 不需要知道任何关于审计或计时器的存在。高阶函数 execution_monitor 承担了逻辑排列的职责
四、Lambda 表达式
如果很多辅助性的逻辑非常简单,如果每用一次都去声明一个函数,不仅会写出大量只有一两行代码的一次性垃圾函数,还会严重污染系统的命名空间
为了解决这种高频、轻量级行为的就地投递问题,Python 引入了 Lambda 表达式 ,也就是通常所说的匿名函数
1. Lambda 语法
Lambda 表达式本质上是一种用于定义轻量级函数的语法糖。它没有函数名,也没有普通的函数声明结构。其标准的语法非常精简:
-
Lambda 关键字:用于声明这是一个匿名函数
-
arguments (参数列表) :函数的输入参数,支持多个参数,用逗号
,隔开。语法规则与普通函数的参数列表完全一致,但不需要加括号 -
冒号:分隔符
-
expression (单一表达式) :函数的执行逻辑本体。核心限制:只能有一条表达式,不能包含复杂的控制语句。计算结果会自动作为函数的返回值返回,不能写 return 关键字
def 声明与 lambda 表达式
python
# 1. 传统 def 声明
def add(x, y):
return x + y
# 2. 等价的 lambda 表达式
add_lambda = lambda x, y: x + y
print(add(5, 3)) # 输出:8
print(add_lambda(5, 3)) # 输出:8
print(type(add_lambda)) # 输出:<class 'function'> -> 证明它在底层依然是一个纯粹的函数对象
2. Lambda 应用场景
Lambda 表达式真正用法,是与高阶函数结合,作为就地临时消费的行为参数直接嵌入到调用中
最经典的场景之一就是自定义排序逻辑。内置的 sorted() 函数或列表的 .sort() 方法是一个标准的高阶函数,它接收一个 key 参数,该参数要求传入一个函数对象,用来决定排序的依据:
python
# 一组存储员工数据的字典列表
employees = [
{"name": "Alice", "age": 30, "salary": 9000},
{"name": "Bob", "age": 25, "salary": 12000},
{"name": "Charlie", "age": 35, "salary": 8000}
]
# 业务需求:按照员工的薪资由低到高进行精准排序
# 利用 lambda 表达式一行流搞定,直接提取出薪资字段作为排序键
sorted_by_salary = sorted(employees, key=lambda emp: emp["salary"])
print(sorted_by_salary)
# 输出:[
# {'name': 'Charlie', 'age': 35, 'salary': 8000},
# {'name': 'Alice', 'age': 30, 'salary': 9000},
# {'name': 'Bob', 'age': 25, 'salary': 12000}
# ]
如果没有 Lambda 表达式,你必须在外部额外定义一个多余函数,代码的紧凑型和直观度会大打折扣
3. Lambda 注意事项
Lambda 表达式虽然简洁优雅,但在实际开发中需要谨慎把握使用尺度,否则非常容易导致代码可读性下降
保持单一表达式
Lambda 在设计之初就是为了处理一眼就能看懂的超轻量级算法。如果一行内堆叠了多层复杂的条件判断,应当立刻重构为标准的函数
python
# 严重的错误示范:在 lambda 中通过嵌套三元表达式塞入复杂逻辑
complex_func = lambda x: "A" if x > 90 else ("B" if x > 80 else ("C" if x > 60 else "D"))
# 正确示范:写 def 函数
def evaluate_grade(score):
if score > 90: return "A"
if score > 80: return "B"
if score > 60: return "C"
return "D"
PEP 8 规范
Python 官方的 PEP 8 代码规范指出:不要显式地将一个 Lambda 表达式赋值给一个变量
如果你需要给一个逻辑命名以供复用,那就应该使用 def 关键字。强行给 Lambda 表达式命名,不仅丧失了匿名的灵活性,还会降低调试时的体验
python
# 不推荐:强行给匿名函数命名
square = lambda x: x ** 2
# 推荐:直接使用 def 声明
def square(x):
return x ** 2
在程序崩溃抛出异常时,使用 def 声明的函数会明确指出是哪个函数名发生了错误;而如果使用命名 Lambda,异常栈只会提示 <lambda> 报错,这会给大规模系统中的 Bug 定位带来极大的困扰
五、Python 常用高阶函数
Python 内置了四个强大的高阶函数:map()、filter()、sorted() 和 reduce()。熟练运用这些工具,可以让你以简洁高效方式优雅地处理大规模数据,实现清洗、过滤和聚合操作
1. map()
map(function, iterable) 是一种数据转换方法。它接受一个转换函数和一个可迭代对象,自动遍历该对象的所有元素,将函数依次应用到每个元素上,最终生成一个新的转换结果序列
python
# 将一组用户注册邮箱统一转换为小写
raw_emails = [" Alice@Gmail.com ", "BOB@outlook.COM ", " charlie@QQ.COM"]
# 使用 lambda 快速清洗字符串去除空格并转为小写
clean_emails_iter = map(lambda email: email.strip().lower(), raw_emails)
# 转换为列表输出
print(list(clean_emails_iter))
# 输出:['alice@gmail.com', 'bob@outlook.com', 'charlie@qq.com']

2. filter()
filter(function, iterable) 用于对数据进行筛选过滤。它接受一个返回布尔值的判定函数和一个可迭代对象,保留所有判定为 True 的元素,过滤掉判定为 False 的元素
python
# 从一组商品库存数据中,筛选出所有库存低于10的商品数量
stock_levels = [150, 4, 88, 0, 12, 9, 200]
danger_stocks = filter(lambda stock: stock < 10, stock_levels)
print(list(danger_stocks)) # 输出:[4, 0, 9]

3. sorted()
sorted(iterable, key=None, reverse=False)的核心在于高阶参数 key。通过向 key 注入一个转换函数,我们能够打破传统的 "按数值大小排序" 的局限,实现按任意自定义规则进行多维排序
python
# 一组待处理的航线数据
flights = ["PEK-SIN", "HND-LAX", "PVG-LHR"]
# 终点站是字符串切片后的后三位 [-3:]
sorted_flights = sorted(flights, key=lambda flight: flight[-3:])
print(sorted_flights)
# 输出:['HND-LAX', 'PVG-LHR', 'PEK-SIN'] (按 LAX, LHR, SIN 字母表升序排序)

4. reduce()
reduce(function, iterable, initializer) 是唯一被移出内置全局命名空间的函数。因为 Python 创始人 Guido 认为它过于隐晦,所以在 Python 3 中将其收拢到了 functools 模块内
reduce 的功能是对可迭代对象进行累积计算。其计算过程如下:首先将前两个元素传入函数并计算结果;然后将该结果作为新参数,与下一个元素再次传入函数。如此迭代处理所有元素,最终返回一个累积计算值
python
from functools import reduce
# 业务需求:计算 1 到 5 的阶乘结果(即 1*2*3*4*5)
numbers = [1, 2, 3, 4, 5]
# lambda x, y 中,x 承载的是上一次的累积成果,y 是本次新数据
factorial_result = reduce(lambda x, y: x * y, numbers)
print(factorial_result) # 输出:120

六、条件表达式
Lambda 表达式的内部只能包含单一的表达式,不能塞入如 if-else 这样的控制语句。然而,在实际开发中,根据某个条件为变量赋予不同的值是最常见的业务需求
为了打破多行分支的代码冗余,Python 引入了条件表达式 ,在其他编程语言中,它通常被称为三元运算符
1. 为什么需要条件表达式
假设我们需要根据用户的权限等级,返回其可享受的折扣率:
python
# 传统的命令式写法
def get_discount_legacy(is_vip):
if is_vip:
discount = 0.8
else:
discount = 1.0
return discount
这段代码虽然清晰,但为了一个简单的二选一逻辑,大张旗鼓地动用了 5 行代码,并在多个分支中重复对 discount 变量进行赋值。这不仅显得臃肿,也打断了声明式代码的流畅度。
条件表达式则允许我们以表达式的形式,将这一判定逻辑浓缩进一行代码中
2. 语法结构
-
condition(判定条件):一个返回布尔值的表达式
-
value_if_true:当前面的 condition 判定为 True 时,表达式返回的值
-
value_if_false:当前面的 condition 判定为 False 时,表达式返回的值
短路求值:
Python 在执行条件表达式时会首先计算中间的 condition。如果为真,则只去计算并返回 value_if_true,右侧的 value_if_false 会被完全忽略;反之亦然。这种机制确保了不会触发多余的计算开销
3. 应用场景示例
变量的高效赋值
python
status_code = 200
# 一行流完成状态文本的生成
message = "请求成功" if status_code == 200 else "服务器异常"
print(message) # 输出:请求成功
Lambda 表达式中的使用
这是条件表达式最核心的使用。有了它,匿名函数就具备了处理二选一逻辑的能力:
python
# 业务需求:给一组数据进行边界安全限制,若数字大于 100 则截断为 100,否则保持原样
clip_signal = lambda x: 100 if x > 100 else x
print(clip_signal(150)) # 输出:100
print(clip_signal(45)) # 输出:45
在返回语句中使用
python
def check_permission(user_role):
# 直接在 return 时进行契约判定
return "Access Granted" if user_role in ("Admin", "Root") else "Access Denied"
print(check_permission("Guest")) # 输出:Access Denied
4. 什么时候不该使用
条件表达式是一把锋利的双刃剑,它的使用原则只有一个:可读性
严禁嵌套
当业务出现了三选一或更多分支时,有些开发者会写出如下嵌套的条件表达式:
python
score = 85
# 恶劣的示范:嵌套三元
grade = "A" if score >= 90 else ("B" if score >= 80 else ("C" if score >= 60 else "D"))
这种代码严重违背了 Python 设计原则。面对多分支,应当回归到标准的 if-elif-else 结构中
严禁混淆语句与表达式
条件表达式的初衷是为了 "计算并返回一个值",而不是为了 "执行一段动作"
python
# 反面模式:在条件表达式里执行 print (极度不推荐)
print("VIP") if is_vip else print("Normal")
七、列表推导式
列表推导式堪称 Python 最具特色的语法特性之一。它将传统的循环遍历、条件筛选、数据转换高度浓缩在方括号内部。它不仅能让代码变得更加精简,其底层在 CPython 解释器中还经过了专门的底层优化,执行效率通常显著高于手写的 for 循环
1. 为什么需要推导式
在传统命令式编程中,创建新列表往往需要遵循 "声明空列表→构建循环→处理逻辑→手动追加" 这一冗长流程:
python
# 传统的命令式循环
squares = []
for x in range(1, 6):
squares.append(x ** 2)
这段代码关注的是 "怎么做(How)" 的步骤。而列表推导式则让我们直接切换到声明式的思维轨道,直接定义 "我要一个什么样的数据集(What)"
2. 基本语法
列表推导式最基本的语法如下:
-
iterable:数据源(如列表、元组、字符串、range 等)
-
for item in:循环驱动,负责遍历数据源中的元素
-
expression(核心表达式):针对每一个拨出来的元素,计算出一个结果,并将其插入新的列表中
ruby
# 列表推导式一行流实现数字平方
squares = [x ** 2 for x in range(1, 6)]
print(squares) # 输出:[1, 4, 9, 16, 25]
3. 条件推导式
推导式真正强大的地方在于它可以与条件判定融合。根据 if 关键字所在的位置不同,它展现出两种不同的语义:
if 放在尾部
当 if 在整条推导式的最右侧时,它扮演的是filter() 的拦截角色。只有满足条件的元素,才会被放行投递到最左侧的表达式中
python
# 从一组设备温度中,只提取出所有"超标温度"(大于 40)
temperatures = [23, 45, 12, 60, 38, 92]
hot_signals = [t for t in temperatures if t > 40]
print(hot_signals) # 输出:[45, 60, 92]
if-else 放在首部
在需要遍历过程中实现二选一状态转换时,可将条件表达式作为推导式最左侧的处理环节
python
# 对一批日志状态码进行分类标记(200为"OK",其余一律为"ERR")
status_codes = [200, 404, 200, 500]
labels = ["OK" if code == 200 else "ERR" for code in status_codes]
print(labels) # 输出:['OK', 'ERR', 'OK', 'ERR']
4. 多层推导式
列表推导式甚至支持嵌套多个 for 循环,这在处理二维列表(矩阵)时非常利落。其嵌套书写顺序与多层 for 循环的顺序完全一致
python
# 将一个二维矩阵扁平化为一维列表
matrix = [
[1, 2, 3],
[4, 5, 6]
]
# 拆解逻辑:for row in matrix(外层循环)-> for val in row(内层循环)
flattened = [val for row in matrix for val in row]
print(flattened) # 输出:[1, 2, 3, 4, 5, 6]
多层推导式最多只能接受 2 层循环嵌套。如果超过 2 层,代码的可读性会发生灾难性的崩塌,此时必须立刻回归到传统的多行 for 循环中
总结
本章从 "函数也是对象" 这一核心思想出发,介绍了函数赋值、函数作为参数和返回值、高阶函数、Lambda 表达式、列表推导式以及 map()、filter()、sorted()、reduce() 等常用函数式编程工具。通过这些内容,我们不仅掌握了更加简洁、灵活的代码编写方式,也进一步理解了 Python 区别于许多传统编程语言的重要特性
下一篇文章我们将继续深入函数进阶内容,学习作用域、闭包与装饰器。这些特性广泛应用于日志记录、权限控制、性能统计等实际开发场景,也是理解 Python 高级编程思想的重要基础
