写代码时,你是否也有这样的抓狂时刻: 面对复杂的嵌套循环,CPU风扇狂转却处理极慢? 还在用字符串拼接处理文件路径,一换系统就报错? 明明几行代码能搞定的逻辑,却写成了几十行的”面条代码”?

作为一名写了十年Python的老司机,我深知效率就是生命。今天不讲枯燥的语法,精选10个冷门但超实用的Python技巧。学会它们,不仅能让你的代码跑得更快,还能让你在Code Review时收获同事崇拜的目光!
技巧1:Pathlib —— 让文件路径操作“优雅化”
场景:还在用 os.path.join 拼接路径?跨平台(Win/Mac)兼容性让你头秃? 原理:pathlib 将路径视为对象而非字符串,支持链式调用,就像搭积木一样简单。
from pathlib import Path
# 旧写法 (os.path)
# import os
# path = os.path.join("data", "2024", "report.csv")
# 新写法 ✨
base_dir = Path("data")
file_path = base_dir / "2024" / "report.csv"
print(file_path.exists()) # 检查是否存在
print(file_path.suffix) # 输出: .csv
✨ 技巧2:Zip与解包 —— 数据的“双人舞”
场景:需要同时遍历两个列表(如姓名和分数),或者将字典的键值对互换。 原理:zip 函数就像拉链,将多个可迭代对象通过索引一一配对。
names = ["Alice", "Bob", "Charlie"]
scores = [85, 92, 78]
# 同时遍历
for name, score in zip(names, scores):
print(f"{name}: {score}")
# ⚠️ 避坑指南:
# 如果列表长度不一致,zip默认截断。
# Python 3.10+ 可用 zip(..., strict=True) 强制检查长度。
⚡️ 技巧3:海象运算符 (:=) —— 赋值与判断一步到位
场景:在 while 循环或 if 判断中,需要先计算值,再检测该值是否满足条件。 原理:Python 3.8 引入的海象运算符,允许在表达式内部进行变量赋值,减少重复计算。
# 旧写法
# line = f.readline()
# while line:
# process(line)
# line = f.readline()
# 新写法 ✨
# while (line := f.readline()):
# process(line)
技巧4:Counter —— 统计狂魔的福音
场景:统计文章中单词出现的频率,或者投票系统中计算票数。 原理:collections.Counter 是字典的子类,专门用于哈希对象计数,比手写 dict.get(key, 0) + 1 快且优雅。
from collections import Counter
data = ['apple', 'orange', 'apple', 'pear', 'orange', 'apple']
counter = Counter(data)
print(counter.most_common(2))
# 输出: [('apple', 3), ('orange', 2)]
✨ 技巧5:字典合并操作符 (|)
场景:你需要将默认配置与用户配置合并,旧的 update() 方法既繁琐又会修改原数据。 原理:Python 3.9+ 引入的合并操作符,语法类似集合的并集,创建新字典而不污染原数据。
default_config = {"host": "localhost", "port": 80}
user_config = {"port": 8080}
# 这里的 user_config 会覆盖 default_config 中的同名key
final_config = default_config | user_config
print(final_config)
# 输出: {'host': 'localhost', 'port': 8080}
⚡️ 技巧6:itertools.chain —— 零内存损耗连接列表
场景:你有三个巨大的列表需要遍历,用 list1 + list2 + list3 会瞬间撑爆内存。 原理:chain 创建一个迭代器,依次返回元素,而不是在内存中创建一个包含所有元素的新列表。
import itertools
list1 = range(10000)
list2 = range(10000)
# 内存友善型 ✨
for item in itertools.chain(list1, list2):
pass # 处理数据
技巧7:Dataclasses —— 告别臃肿的类定义
场景:定义一个只用来存数据的类,却要写 __init__, __repr__, __eq__ 等一堆样板代码。 原理:@dataclass 装饰器自动生成上述方法,让代码回归数据定义的本质。
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
is_active: bool = True
u1 = User("Neo", 30)
print(u1)
# 输出: User(name='Neo', age=30, is_active=True)
✨ 技巧8:with语句与Contextlib —— 自动“关门”
场景:除了文件操作,数据库连接、线程锁等也需要自动关闭/释放,防止资源泄露。 原理:利用 contextlib 库,可以将任意生成器函数转化为上下文管理器。
from contextlib import contextmanager
@contextmanager
def open_db():
print(" 连接数据库...")
yield "DB_CONNECTION"
print("❌ 关闭连接!")
with open_db() as db:
print(f"正在使用 {db} 进行查询")
# 输出顺序:连接 -> 查询 -> 关闭
⚡️ 技巧9:性能王者 —— 列表推导式 vs For循环
场景:将一个列表中的数字全部平方。 原理:列表推导式(List Comprehension)在C语言层面进行了优化,比解释器层面的 for 循环快得多。
import timeit
# 普通 For 循环
def loop_method():
res = []
for i in range(10000):
res.append(i**2)
# 列表推导式 ✨
def list_comp_method():
res = [i**2 for i in range(10000)]
# 性能实测
t1 = timeit.timeit(loop_method, number=1000)
t2 = timeit.timeit(list_comp_method, number=1000)
print(f"For循环耗时: {t1:.4f}s")
print(f"推导式耗时: {t2:.4f}s")
# 结果一般显示推导式快 30%-50% 左右!
技巧10:Else子句 —— 循环的“侦察兵”
场景:在列表中查找元素,如果找完整个列表都没找到,才执行某个操作(列如报错)。 原理:for…else 语法中,只有当循环正常结束(未被break打断)时,才会执行 else 块。
def find_user(users, target):
for user in users:
if user == target:
print("✅ 找到了!")
break
else:
# 不需要使用 flag 变量标记是否找到
print(" 未找到该用户")
find_user(["A", "B"], "C") # 输出: 未找到该用户
避坑指南:可变参数的陷阱
你知道吗?许多新手(甚至老手)都栽在这个坑里:千万不要用可变对象(如列表、字典)作为函数的默认参数!
# ❌ 错误示范
def add_item(item, box=[]):
box.append(item)
return box
print(add_item("A")) # ['A']
print(add_item("B")) # 竟然输出 ['A', 'B'] ?!
# 缘由:默认参数在函数定义时只创建一次,后续调用共享同一个列表对象。
# ✅ 正确修正
def add_item(item, box=None):
if box is None:
box = []
box.append(item)
return box
总结
编程不仅仅是实现功能,更是一门平衡的艺术。
- pathlib 和 dataclasses 提升了代码的可读性;
- chain 和生成器优化了内存占用;
- 列表推导式则榨干了 CPU 的性能。
当你开始组合使用这些技巧时(列如在 dataclass 中使用 pathlib 路径,并用列表推导式处理数据),你会发现写代码变得像弹钢琴一样流畅!
收藏学习了
收藏了,感谢分享