Python 的关键字是解释器保留的词,不能拿来做变量名、函数名或类名。数量很少,但每一类都有明确分工。
截至 Python 3.12,keyword.kwlist 里有 35 个硬关键字:
import keyword
print(len(keyword.kwlist)) # 35
print(keyword.softkwlist) # ['_', 'case', 'match', 'type']softkwlist 是软关键字——它们只在特定语法位置有意义,在别处完全可以当普通标识符用。match/case(3.10+)、_、type 属于这一类。网上流传的”Python 关键字列表”经常把这四个混进硬关键字,也经常把 int、float 这些内置类型当成关键字,这两种说法都不准确。
下面按职责把 35 个硬关键字分成 12 组。
条件与分支(3 个)
if、elif、else 构成互斥分支链。elif 是 else: if 的简写,Python 允许任意层级,但超过三层通常说明该拆函数了。
score = 85
if score >= 90:
level = "优秀"
elif score >= 70:
level = "良好"
else:
level = "及格"
print(level) # 良好elif 的条件从上到下依次求值,一旦命中某个分支,其余分支不再求值。所以把范围窄的条件放前面、宽的放后面。
循环与循环控制(5 个)
for 遍历可迭代对象,while 基于条件反复执行。break 直接跳出最内层循环,continue 跳过本轮剩余语句进入下一轮,pass 是空语句,常用于占位(空的 if 或 class 体必须有至少一条语句)。
for i in range(10):
if i == 5:
break
if i % 2 == 0:
continue
print(i)
1. 输出:1 3break 和 continue 只作用于最内层循环。嵌套循环里想跳出外层,得配合 else 子句或把内层封成函数后 return。
def find_first_even(rows):
for row in rows:
for value in row:
if value % 2 == 0:
return value
return None异常处理(5 个)
try 标记受保护代码块,except 捕获异常,finally 无论是否出错都会执行,raise 主动抛出异常,assert 在断言失败时抛 AssertionError。
try:
1 / 0
except ZeroDivisionError:
print("除数不能为 0")
finally:
print("程序结束")
1. 输出:除数不能为 0 / 程序结束assert 只在优化模式下(python -O)会被跳过,不要用它做用户输入校验——那种场景应该显式 raise ValueError。
age = 15
try:
if age < 18:
raise ValueError("年龄必须大于等于 18")
except ValueError as exc:
print(f"校验失败:{exc}")
1. 输出:校验失败:年龄必须大于等于 18except 后面可以写多个异常类型,也可以用 as 绑定异常对象:
try:
import tomllib
except ModuleNotFoundError as exc:
print(f"需要 Python 3.11+,当前环境:{exc}")函数与类(3 个)
def 定义函数,class 定义类,lambda 创建匿名函数。
def add(a, b):
return a + b
mul = lambda x, y: x * y
print(add(2, 3)) # 5
print(mul(3, 4)) # 12lambda 的函数体只能是单个表达式,不能写语句。性能上和 def 没差别(都用同一个函数对象类型),选 lambda 只是为了少写几行或作为回调传递。
class Person:
def __init__(self, name):
self.name = name
p = Person("Alice")
print(p.name) # Alice返回与产出(2 个)
return 结束函数并返回值,函数体没写 return 时默认返回 None。yield 让函数变成生成器。
def gen_numbers():
yield 1
yield 2
g = gen_numbers()
print(next(g)) # 1
print(next(g)) # 2return 和 yield 出现在同一个函数的不同分支是合法的,但 yield 一旦出现,调用该函数得到的就是生成器对象,而不是普通返回值。
作用域(2 个)
global 把函数内赋值绑定到模块级变量,nonlocal 绑定到外层函数作用域(不是模块级,也不是全局)。
x = 10
def modify_x():
global x
x = 20
modify_x()
print(x) # 20def outer():
x = 10
def inner():
nonlocal x
x = 20
inner()
print(x)
outer() # 20nonlocal 要求外层确实存在同名绑定,否则抛 SyntaxError。注意 global 只影响赋值目标,对该名字的读取仍按正常作用域规则走。
导入(3 个)
import、from、as 控制模块引入方式。
import math
from math import pi
import os as operating_system
print(math.pi) # 3.141592653589793
print(pi) # 3.141592653589793
print(operating_system.sep) # 当前平台路径分隔符import a 之后 a 是一个模块对象,a.b 逐级访问;from a import b 之后 b 直接绑定到 a 模块里的那个对象。前者能清楚地看出名字来自哪里,后者更适合处理名字冲突(用 as 起别名)。
逻辑与比较(5 个)
and、or、not 是逻辑运算,in 是成员判断,is 是身份判断。这五个最容易被忽略。
print(1 < 2 < 3) # True,链式比较
print("a" in "abc") # True
print([] in [[], []]) # True,按相等性判断
print([] is [[], []]) # False,两个不同的列表对象is 比较的是对象身份(是不是同一个对象),== 比较的是值。所以判断 None 用 is None,不要用 == None;同理不要用 is 比较字符串或数字。
and/or 会短路并返回操作数本身,不是布尔值:
print(0 or "fallback") # fallback
print(1 and "value") # valuenot 优先级低于比较运算符,not a == b 等价于 not (a == b)。
上下文管理(1 个)
with 把资源获取和释放绑定成一块,无论块内是正常结束还是抛异常,清理逻辑都会执行。
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as tmp:
target = Path(tmp) / "test.txt"
target.write_text("hello", encoding="utf-8")
with target.open("r", encoding="utf-8") as f:
content = f.read()
print(content) # hello
1. 离开 with 块,目录连同文件一起被清理背后是 __enter__ 和 __exit__ 两个协议方法(前后各两个下划线),自定义资源管理器也靠它们。
from time import time
class Timer:
def __enter__(self):
self.start = time()
return self
def __exit__(self, exc_type, exc, tb):
print(f"耗时 {time() - self.start:.6f}s")
return False # 返回 True 会吞掉异常
with Timer():
sum(range(100000))异步(2 个)
async 修饰协程函数,await 挂起当前协程等待另一个协程完成。
import asyncio
async def wait_task():
await asyncio.sleep(1)
print("等待 1 秒后执行")
asyncio.run(wait_task())await 只能出现在 async def 定义的作用域内。async def 定义的是协程函数,调用它得到的是协程对象,必须 await 或交给事件循环调度才会有实际效果。
删除(1 个)
del 删除绑定,不是释放内存。CPython 用引用计数,名字被删掉后若无人再持有,内存才随之回收。
lst = [1, 2, 3]
del lst[1]
print(lst) # [1, 3]
d = {"a": 1}
del d["a"]
print(d) # {}del 只能作用于变量名、属性、下标这三类”可删除对象”,不能用在函数返回值或字面量上。
字面量常量(3 个)
True、False、None 是三个关键字字面量,不是变量,运行期不可重新赋值。
result = None
if result is None:
print("无结果") # 无结果None 是 NoneType 类型的唯一实例。所有对象的 __bool__ 缺省返回真,因此 None、、""、[] 在条件里都为假——但判断”有没有值”时要用 is None,因为 和 "" 也是合法的”有值但为空”的场景。
软关键字不是关键字
match/case(3.10+)在别处完全可以当变量名:
match = "a regex match"
print(match) # a regex matchtype(3.12+ 起是软关键字)同样如此:
type = 42
print(type) # 42_ 习惯上表示”这个值我不要”,但它不是关键字:
for _, value in enumerate([10, 20, 30]):
print(value) # 10 20 30关键字使用注意事项
- 不能做标识符。
if = 10直接SyntaxError。但可以带下划线前缀躲开,比如class_ = 1。 - 区分关键字与内置函数。
int、float、str、list是内置类型(也是内置函数),不是关键字;print、len、range是内置函数,也不是关键字。它们可以被变量名覆盖,这也是最常见的坑——list = [1,2]之后list()就废了。 - 版本兼容。
match/case需要 3.10+,except*需要 3.11+,type语句需要 3.12+。写库时先确认目标版本下限。 - 关键字是区分大小写的。
IF不是关键字,可以做变量名。
相关文档
- Python 35个关键字详解 —— 本篇
- Python 内置函数详解 ——
int、print等的完整说明 - Go语言25个关键字详解 —— 另一门语言的关键字对照