Python 核心语法扫盲:列表推导式到装饰器
Python 中那些看似简单但容易混淆的语法点——列表推导式、生成器、args/kwargs、装饰器、yield 的完整梳理。
Python 核心语法扫盲:列表推导式到装饰器
背景
工作中常用 Python 写工具脚本和 AI/LLM 项目,但语法细节经常记不住。这份笔记整理了从列表推导式到装饰器的核心语法。
列表推导式
[x*2 for x in range(10) if x%2 == 0]
阅读顺序从右往左:for x in range(10) 循环 → if x%2==0 过滤 → x*2 表达式。等价于:
result = []
for x in range(10):
if x % 2 == 0:
result.append(x * 2)
嵌套列表推导式(例如二维数组展平):
# [[1,2],[3,4]] → [1,2,3,4]
[y for x in [[1,2],[3,4]] for y in x]
这里阅读顺序是:外层 for → 内层 for → 表达式。
dict.setdefault() vs update()
一个我常搞混的地方:
# 错误写法
group = {}
for item in data:
key = item['type']
group[key] = group.get(key, [])
group[key].append(item)
# 正确写法
group = {}
for item in data:
group.setdefault(item['type'], []).append(item)
# setdefault: 如果 key 不存在就设默认值,返回该 key 对应的 value
setdefault 比 get + 赋值更简洁,且保证原子性。
*args 和 **kwargs
def func(*args, **kwargs):
# args → 元组 (1, 2, 3)
# kwargs → 字典 {'a': 1, 'b': 2}
pass
func(1, 2, 3, a=1, b=2)
常见于:装饰器包装、super() 调用父类方法、设计灵活 API。
生成器 yield
def read_large_file(path):
with open(path) as f:
for line in f:
yield line.strip() # 一次一行,不占内存
生成器 vs 列表:列表一次性生成所有元素放在内存里;生成器惰性求值,用到才出。处理大文件时必须用生成器。
装饰器
装饰器是在不修改原函数代码的前提下添加功能的工具:
def log_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.2f}s")
return result
return wrapper
@log_time
def slow_function():
time.sleep(1)
@log_time 等价于 slow_function = log_time(slow_function)。本质是高阶函数——外层接收函数,内层增强行为。
带参数的装饰器需要多包一层:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(n):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def say_hello():
print("hello")
总结
Python 的这些语法特性让代码更简洁,但简洁不等于简单。理解底层机制(闭包、高阶函数、惰性求值)才能写出不出 Bug 的 Python 代码。