写得更像 Python:让代码一下子变地道的 7 个习惯

有学员问我:「村长,我代码能跑,怎么一眼看就是新手写的?」
通常不是语法问题,而是思路还带着别的语言的口音。今天聊 7 个习惯,改完不用多加一行功能,代码味道立刻不一样。
1. EAFP:先做,出错再说
Python 圈有个说法叫 EAFP(Easier to Ask Forgiveness than Permission),相对的是 LBYL(Look Before You Leap)。
data = {"name": "村长"}
# LBYL:先检查再动手
if "age" in data:
age = data["age"]
else:
age = 0
# EAFP:村长写法
try:
age = data["age"]
except KeyError:
age = 0
# 更地道的写法
age = data.get("age", 0)
Python 的异常处理很便宜,先试再兜底通常比层层判断更清爽,也避开「检查完状态又变了」的竞争问题。
2. with:打开的东西让它自己关
# 容易漏
f = open("data.txt", encoding="utf-8")
text = f.read()
f.close()
# 村长写法
with open("data.txt", encoding="utf-8") as f:
text = f.read()
离开 with 块会自动清理,哪怕中间抛了异常也照样关。文件、锁、数据库连接、临时目录都适用。
村长划重点:判断标准很简单——只要这个对象有
__enter__/__exit__(或你手动写了 try/finally 去关它),就交给with。
3. 能用生成器就别先造整个列表
# 一次性把一百万个数全存进内存
total = sum([n * n for n in range(1_000_000)])
# 一个个来,内存几乎不涨
total = sum(n * n for n in range(1_000_000))
把方括号去掉,列表推导式就变成生成器表达式。数据量一大,差别就是「跑得动」和「内存炸了」。
4. 绝对别用可变对象当默认参数
这是新手最经典的坑:
# 错的:默认列表在函数定义时创建一次,所有调用共用
def add(item, bucket=[]):
bucket.append(item)
return bucket
print(add("a")) # -> ['a']
print(add("b")) # -> ['a', 'b'] 咦?
# 对的
def add(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
return bucket
列表、字典、集合当默认值都会中招,一律用 None 占位再在函数里创建。
5. 判断 None 用 is,不用 ==
value = None
if value is None: # 推荐
...
if not value: # 危险:0、空字符串、空列表也会进来
...
is 比较的是「是不是同一个对象」,None 是单例,用它最准确。同理,判断布尔值时先想清楚「空列表」算不算 False。
6. 拼字符串用 join,别在循环里加
words = ["Python", "小技巧", "真好用"]
# 循环里反复创建新字符串
s = ""
for w in words:
s += w
# 村长写法
s = "".join(words)
s = " · ".join(words) # 还能带分隔符
字符串不可变,循环里 += 会不断产生新对象;join 一次算好长度、一次分配。
7. 用下划线告诉别人「我故意不要」
# 只要值,不要下标
for _ in range(3):
print("再来一次")
# 只要第一个和最后一个
first, *_, last = [10, 20, 30, 40, 50]
# 解包时忽略中间字段
name, _, _, score = ("小明", "男", "杭州", 95)
_ 是约定俗成的「占位变量」,读代码的人一眼知道这个值被有意丢掉了,比起名 temp2 清楚得多。
村长划重点:在交互解释器里
_还有另一层含义——保存上一次表达式的结果。写脚本时没有这个副作用,可以放心当占位符。
小结
| 习惯 | 一句话 |
|---|---|
| EAFP | 先做,出错再兜底 |
with | 资源让它自己关 |
| 生成器 | 别急着造整个列表 |
| 默认参数 | 用 None,别用 [] |
is None | 别把 0 和空列表误判成 None |
join | 拼字符串一次到位 |
_ | 明确告诉别人「我不要」 |
这些不是死规矩,是 Python 社区多年攒下来的共识。想看完整版,官方的 PEP 8 编码风格指南 值得读一遍;我们教程第 4 章末尾也有中文摘要。
我是村长,不好奇编程的站长。写代码这件事,能跑只是起点,好读才是本事。
