Python 35个关键字详解

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 3

break 和 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. 输出:校验失败:年龄必须大于等于 18

except 后面可以写多个异常类型,也可以用 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))  # 12

lambda 的函数体只能是单个表达式,不能写语句。性能上和 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))  # 2

return 和 yield 出现在同一个函数的不同分支是合法的,但 yield 一旦出现,调用该函数得到的就是生成器对象,而不是普通返回值。

作用域(2 个)

global 把函数内赋值绑定到模块级变量,nonlocal 绑定到外层函数作用域(不是模块级,也不是全局)。

x = 10

def modify_x():
    global x
    x = 20

modify_x()
print(x)  # 20
def outer():
    x = 10

    def inner():
        nonlocal x
        x = 20

    inner()
    print(x)

outer()  # 20

nonlocal 要求外层确实存在同名绑定,否则抛 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")     # value

not 优先级低于比较运算符,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 match

type(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 不是关键字,可以做变量名。

相关文档

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇