跳到主要内容

Python 速查表 —— 100+ 段地道 Python 代码,含异步、类型提示与常见坑

Python 速查表,100+ 段地道 Python 代码片段,涵盖字符串/列表/字典/文件/异步,带真实例子。

  • 本地处理
  • 分类 开发运维
  • 适合 格式化、校验、压缩或检查和代码相关的文本。
102
基础 (7)

变量赋值与多重赋值

x = 42
name = "Lei"
a, b, c = 1, 2, 3
x, y = y, x   # swap, no temp variable

Python 是动态类型,赋值就是把名字绑到对象上。一行多赋值很常见;交换两个变量用元组拆包,不用临时变量。

变式
a = b = c = 0   # chained, all point to same object
first, *rest = [1, 2, 3, 4]   # 1, [2,3,4]

数值类型 int / float / complex / decimal

n = 10                # int, 任意精度
pi = 3.14             # float, IEEE 754 双精度
z = 2 + 3j            # complex
from decimal import Decimal
price = Decimal("0.1") + Decimal("0.2")   # 精确 0.3

int 任意精度(3 ** 200 也能算)。float 是 IEEE 754,0.1 + 0.2 不等于 0.3。算钱必用 Decimal,且参数要传字符串。

变式
0.1 + 0.2 == 0.3   # False!
from fractions import Fraction; Fraction(1, 3)

bool 与真假值判断

bool(0)         # False
bool("")        # False
bool([])        # False
bool(None)      # False
bool("False")   # True (非空字符串都是 True)
bool([False])   # True (列表非空就是 True)

假值只有这几个:0、0.0、""、[]、{}、set()、None、False。其他都是真值 —— 字符串 "False" 是真,列表 [False] 也是真。

变式
if items:  # 比 if len(items) > 0 更地道
x = a or "default"  # a 为假值时取 default

None 单例

x = None
if x is None:        # ✅ 推荐
    print("空值")
if x == None:        # 能跑但不地道
    pass

None 是单例 —— 必须用 is None / is not None 判断,不要写 == None。is 比较对象身份,== 是值相等,可被重载坑掉你。

用 isinstance 判断类型

isinstance(x, int)             # True if x is int (or bool!)
isinstance(x, (int, float))    # 接受多种类型
type(x) is int                 # 严格相等,不认子类

用 isinstance 而不是 type() == —— isinstance 认继承。坑:bool 是 int 的子类,isinstance(True, int) 是 True。

变式
# 排除 bool:isinstance(x, int) and not isinstance(x, bool)

print 与 input

print("a", "b", "c")               # 默认空格分隔
print("a", "b", sep="-")           # "a-b"
print("loading", end="")           # 不换行
print("err msg", file=sys.stderr)  # 打到 stderr
name = input("name: ")             # 读一行(返回 str,不含换行)
age = int(input("age: "))          # 数字记得转

print 接受 sep= 和 end=。input() 返回字符串(不含换行),要数字得手动 int() / float()。

range 区间序列

range(5)            # 0, 1, 2, 3, 4
range(2, 7)         # 2, 3, 4, 5, 6
range(0, 10, 2)     # 0, 2, 4, 6, 8 (步长)
range(10, 0, -1)    # 10, 9, 8, ..., 1 (反向)
list(range(5))      # [0, 1, 2, 3, 4]

range(stop) / range(start, stop) / range(start, stop, step)。惰性的 —— 迭代时才出数。stop 不包含。

字符串 (10)

f-string(现代格式化首选)

name = "Lei"
age = 30
s = f"{name} is {age}"            # "Lei is 30"
pi = 3.14159
s = f"{pi:.2f}"                   # "3.14"
n = 1234567
s = f"{n:,}"                      # "1,234,567"
s = f"{name=}, {age=}"            # debug: "name='Lei', age=30"

f-string(3.6+)是最快、最易读的格式化方式。:.2f 保留小数,:, 加千位分隔符,{var=} 自带变量名打印 —— 调试神器。

变式
f"{x:>10}"   # 右对齐宽 10
f"{x:0>5}"   # 左补 0 到 5 位
f"{x:.0%}"   # 百分比

.format() 和 % 老写法

"Hello, {}!".format("Lei")
"{0} {1} {0}".format("a", "b")    # "a b a"
"{name} is {age}".format(name="Lei", age=30)
"Hello, %s! You are %d." % ("Lei", 30)

.format() 和 % 还能用,老项目里也常见。新代码推荐 f-string。

split / join 字符串与列表互转

"a,b,c".split(",")              # ['a', 'b', 'c']
"a b  c".split()                # ['a', 'b', 'c']  (默认按空白切,连续空白当一个)
",".join(["a", "b", "c"])       # "a,b,c"
"\n".join(lines)                # 拼成多行字符串

split() 不传参数按任意空白切并合并连续空白。join() 是字符串方法(分隔符在左),不是列表方法 —— 这是新手第一个坑。

变式
"a,b,,c".split(",")   # ["a", "b", "", "c"]  (空段保留)
"a,b,c".split(",", 1)   # ["a", "b,c"]  (限制 split 次数)

strip / lstrip / rstrip 去空白

"  hello  ".strip()           # "hello"
"  hello  ".lstrip()          # "hello  "
"  hello  ".rstrip()          # "  hello"
"xxhelloxx".strip("x")        # "hello"
"https://".rstrip("/")        # "https:"

strip() 默认去空白;传字符串是去那个字符集里的任意字符。坑:rstrip("ing") 是去 i/n/g 任意字符,不是去尾部的 "ing" 子串。

变式
# Python 3.9+ 才有去前后缀 substring 的方法:
"running".removesuffix("ing")   # "runn"
"running".removeprefix("ru")    # "nning"

replace 字符串替换

"hello world".replace("world", "Lei")    # "hello Lei"
"a-b-c-d".replace("-", "_", 2)            # "a_b_c-d"  (限制次数)
import re
re.sub(r"\d+", "#", "abc 123 def 456")    # "abc # def #"  (正则替换)

str.replace() 是普通子串替换,要正则用 re.sub()。replace() 返回新字符串 —— 字符串不可变。

startswith / endswith / in

url.startswith("https://")
filename.endswith((".jpg", ".png", ".gif"))   # 元组:满足任一即可
"lei" in "hello lei"                          # 子串包含
"lei" in ["lei", "han"]                       # 列表 in O(n)
"lei" in {"lei", "han"}                       # 集合 in O(1)

startswith / endswith 接受元组 —— 多扩展名一行搞定。in 在 list/string 上是 O(n),set/dict 上是 O(1),性能差距巨大。

大小写转换

"hello".upper()        # "HELLO"
"HELLO".lower()        # "hello"
"hello world".title()  # "Hello World"
"Hello".casefold()     # "hello"  (比 lower 更激进,能正确处理德语 ß)
"  Hello  ".swapcase() # "  hELLO  "

lower() 处理 ASCII。casefold() 是大小写无关比较的正式做法 —— 能正确处理德语 ß → ss。

字符串切片与索引

s = "hello"
s[0]        # 'h'
s[-1]       # 'o'
s[1:4]      # "ell"
s[:3]       # "hel"
s[::-1]     # "olleh"  (反转,最骚的一行)
s[::2]      # "hlo"    (步长 2)

切片是 [start:stop:step],stop 不包含。负数从末尾数。s[::-1] 是反转字符串的骚操作 —— 一行搞定。

编码与解码 encode / decode

"你好".encode("utf-8")              # b'\xe4\xbd\xa0\xe5\xa5\xbd'
b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode("utf-8")  # "你好"
"abc".encode()                      # 默认 UTF-8
# 容错:errors="ignore" / "replace" / "strict"(默认)
b'\xff\xfe'.decode("utf-8", errors="replace")    # "��"

str → bytes 用 .encode(),bytes → str 用 .decode(),默认 UTF-8。errors="replace" / "ignore" 让坏字节不抛异常。

多行字符串与 textwrap

s = """第一行
第二行
第三行"""
import textwrap
textwrap.dedent("""
    缩进的多行字符串
    自动去掉前导空格
""")
textwrap.fill("超长一段话", width=40)

三引号字符串保留换行。textwrap.dedent 去掉每行共同的前导空白 —— 内嵌 SQL/模板特别好用。

列表 (12)

append / extend / insert

xs = [1, 2, 3]
xs.append(4)              # [1, 2, 3, 4]   单个元素
xs.extend([5, 6])         # [1, 2, 3, 4, 5, 6]   合并另一个可迭代
xs += [7, 8]              # 等价于 extend
xs.insert(0, 0)           # [0, 1, 2, 3, ...]   指定位置插
xs.append([9, 10])        # [..., [9, 10]]   坑:嵌套了一层

append 加一个元素。extend(或 +=)合并一个可迭代。经典 bug:append([9, 10]) 是把整个列表当一个元素塞进去,套了一层。

列表切片与切片赋值

xs = [1, 2, 3, 4, 5]
xs[1:4]              # [2, 3, 4]
xs[:]                # [1, 2, 3, 4, 5]   浅拷贝
xs[::-1]             # [5, 4, 3, 2, 1]   反转
xs[1:3] = [20, 30]   # 切片赋值:原地修改
xs[::2] = [10, 30, 50]   # 步长切片赋值,两边长度要一致

切片语法和字符串一样。xs[:] 是浅拷贝的经典写法。切片赋值是原地修改 —— 批量替换很方便。

list 推导式

squares = [x * x for x in range(10)]
evens = [x for x in nums if x % 2 == 0]
matrix = [[i * j for j in range(5)] for i in range(5)]
# 双 for 拍平嵌套:
flat = [x for row in matrix for x in row]
# 带 else 的写法(注意 if 位置变了):
labels = ["even" if x % 2 == 0 else "odd" for x in nums]

list 推导地道又快,一般比 for + append 还快。过滤 if 写在末尾;三元 if/else 必须写在 for 前面 —— 位置不一样,新手常搞混。

变式
# 三个以上推导嵌套就拆 for 循环吧,可读性优先

map / filter 函数式写法

list(map(str, [1, 2, 3]))             # ["1", "2", "3"]
list(map(lambda x: x * 2, nums))      # 不推荐,写成推导更地道
list(filter(lambda x: x > 0, nums))   # 不推荐,写成 [x for x in nums if x > 0]
# 多个可迭代一起:
list(map(lambda a, b: a + b, [1, 2], [10, 20]))   # [11, 22]

map 和 filter 返回的是迭代器,要 list() 包一下才能看。一次性用 lambda 的场景 —— 写 list 推导更地道。

sorted / sort / key / reverse

sorted([3, 1, 2])                  # [1, 2, 3]   返回新列表
xs.sort()                          # 原地排序,返回 None
sorted(words, key=len)             # 按长度
sorted(users, key=lambda u: u.age) # 按属性
from operator import itemgetter, attrgetter
sorted(rows, key=itemgetter(2))    # 比 lambda 快一点
sorted(xs, reverse=True)           # 降序
# 多列排序:稳定排序,从次要到主要倒着 sort
sorted(rows, key=lambda r: (r[0], -r[1]))   # 第 1 列升、第 2 列降

sorted() 返回新列表,.sort() 原地排序且返回 None —— 不要写 xs = xs.sort(),那是个 None。key=itemgetter 比 lambda 快一点。Python sort 是稳定排序。

reverse / reversed

xs.reverse()                    # 原地反转,返回 None
list(reversed(xs))              # 返回新列表
xs[::-1]                        # 也是反转,最简洁

.reverse() 原地修改;reversed() 返回迭代器(要 list() 包);xs[::-1] 返回新列表,最短。

列表去重(保留顺序)

# 不在乎顺序:
list(set(xs))
# 保留首次出现顺序(3.7+ dict 有序):
list(dict.fromkeys(xs))
# 复杂对象去重(按某 key):
seen = set()
uniq = [x for x in xs if not (x in seen or seen.add(x))]

set() 去重丢顺序。dict.fromkeys() 去重且保留首次出现顺序(3.7 起 dict 有序,可放心用)。

enumerate 同时拿索引和值

for i, v in enumerate(items):
    print(i, v)
for i, v in enumerate(items, start=1):    # 从 1 开始
    print(i, v)
# 反例(不要写):
for i in range(len(items)):
    print(i, items[i])      # 不地道

enumerate(seq) 给你 (index, value) 对 —— 永远不要写 for i in range(len(seq))。start= 改起始索引。

zip 多个可迭代并行遍历

names = ["Lei", "Han", "Mei"]
ages = [30, 25, 28]
for n, a in zip(names, ages):
    print(n, a)
# 转字典:
d = dict(zip(names, ages))
# 转置矩阵:
list(zip(*matrix))
# 3.10+ strict 模式,长度不一致就抛错:
zip(names, ages, strict=True)

zip 把多个可迭代两两配对,默认按最短的截断。zip(*matrix) 转置矩阵。3.10+ strict=True 长度不一致直接抛错,避免静默截断。

all / any 列表逻辑判断

all([True, True, True])      # True
all([])                       # True   (空集合默认 True,反直觉)
any([False, False, True])     # True
any([])                       # False
# 实战:
all(x > 0 for x in nums)      # 全部为正
any(s.startswith("error") for s in logs)

all() 全为真才 True(空集合按空真规则返回 True,反直觉)。any() 至少一个为真就 True。传生成器表达式可短路提前结束。

sum / min / max 聚合

sum([1, 2, 3])                       # 6
sum([1, 2, 3], 100)                   # 106   (起始值)
max([1, 2, 3])
min(["apple", "banana"], key=len)     # "apple"
max(users, key=lambda u: u.age)
# 3.4+ 提供默认值:
min([], default=0)                    # 不抛错

min/max 接受 key= 函数 —— 找最长字符串/最年轻用户特别方便。空可迭代会抛 ValueError,传 default= 不抛。

pop / remove / del

xs = [10, 20, 30, 40]
xs.pop()         # 删最后一个,返回 40,xs = [10, 20, 30]
xs.pop(0)        # 删第 0 个,返回 10,xs = [20, 30]
xs.remove(30)    # 按值删第一个匹配的
del xs[0]        # 按索引删(不返回值)
del xs[1:3]      # 按切片删

pop 返回被删的元素。remove 按值删第一个匹配(找不到抛 ValueError)。del 是语句不是表达式,没返回值。

字典 (8)

dict 基本操作

d = {"name": "Lei", "age": 30}
d["name"]              # "Lei"
d["email"] = "x@y.z"   # 加键
del d["age"]           # 删键
"name" in d            # 判键存在
len(d)
list(d.keys()), list(d.values()), list(d.items())

dict 是哈希表,平均 O(1) 查找。3.7 起 dict 保证插入顺序 —— 这是语言规范,不是实现细节,可放心依赖。

dict.get 安全取值

d = {"a": 1}
d["b"]              # KeyError
d.get("b")          # None
d.get("b", 0)       # 0   (默认值)
# 嵌套取值的常见写法:
d.get("user", {}).get("name", "anonymous")

d[k] 找不到抛 KeyError;d.get(k, 默认) 返回默认。嵌套取值时链式 .get("x", {}).get(...) 是常见安全写法。

dict.setdefault 一次性"取 or 初始化"

groups = {}
for name, group in pairs:
    groups.setdefault(group, []).append(name)
# 等价于:
from collections import defaultdict
groups = defaultdict(list)
for name, group in pairs:
    groups[group].append(name)

setdefault 有就返回,没有就设并返回默认值。defaultdict(list) 是更优雅的分组写法。

dict.update 合并字典

a = {"x": 1, "y": 2}
b = {"y": 20, "z": 30}
a.update(b)              # a 变成 {"x":1, "y":20, "z":30}
# 3.5+ 解包合并(返回新字典):
merged = {**a, **b}
# 3.9+ | 运算符:
merged = a | b
a |= b                   # 原地合并

update 原地修改 a。{**a, **b} 或 3.9+ 的 a | b 返回新字典。冲突时后者覆盖前者。

dict 推导式

{x: x * x for x in range(5)}              # {0:0, 1:1, 2:4, 3:9, 4:16}
{k: v for k, v in items if v is not None}  # 过滤 None 值
{v: k for k, v in d.items()}              # 反转 kv
# 多个源:
{k: a[k] + b[k] for k in a.keys() & b.keys()}  # 共同键求和

语法和 list 推导一样,但是 key:value。常用于过滤 None、反转 kv、临时建查表。

collections.Counter

from collections import Counter
c = Counter("abracadabra")
# Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
c.most_common(3)              # [('a', 5), ('b', 2), ('r', 2)]
c1 + c2                        # 计数相加
c1 - c2                        # 计数相减(负数被截)
c1 & c2, c1 | c2               # 取最小 / 最大

Counter 是专门做计数的 dict 子类。most_common(n) 给前 n 个。支持 + - & | 做多重集合运算。

collections.defaultdict

from collections import defaultdict
counts = defaultdict(int)        # 默认 0
for w in words:
    counts[w] += 1               # 不用先判 in
buckets = defaultdict(list)
for x in items:
    buckets[x.group].append(x)
nested = defaultdict(lambda: defaultdict(int))   # 嵌套 dict

defaultdict 首次访问就自动创建默认值。defaultdict(int) 计数,defaultdict(list) 分组,lambda 套娃做嵌套。

OrderedDict(3.7 后基本可弃用)

from collections import OrderedDict
od = OrderedDict()
od["a"] = 1
od["b"] = 2
od.move_to_end("a")       # 移到末尾
od.popitem(last=False)    # 弹首元素(普通 dict 没这俩方法)

3.7 后普通 dict 已经保序,大部分场景 OrderedDict 可换成 dict。要用 move_to_end / popitem(last=False) 才有必要保留。

集合 (5)

set 创建与基本操作

s = {1, 2, 3}
empty = set()           # 注意:{} 是 dict 不是 set
s.add(4)
s.discard(99)           # 不抛错;remove(99) 会抛 KeyError
2 in s                  # O(1)
len(s)

set 无序、唯一、O(1) 成员判断。空集合是 set() 不是 {}({} 是空 dict)。discard() 是不抛错版的 remove()。

set 交并差

a = {1, 2, 3}
b = {2, 3, 4}
a | b      # 并集 {1, 2, 3, 4}
a & b      # 交集 {2, 3}
a - b      # 差集 {1}
a ^ b      # 对称差 {1, 4}
a <= b     # 子集判断
a >= b     # 超集判断

set 运算符最易读。也有 .union() .intersection() 等方法名版,可读性上运算符赢。

frozenset 可哈希集合

fs = frozenset([1, 2, 3])
# 可以做 dict 的键、放进 set 里
d = {fs: "value"}
s = {frozenset([1, 2]), frozenset([3, 4])}

frozenset 不可变可哈希 —— 能当 dict 的 key、能放进 set 里。普通 set 都不行。

set 去重

# 简单去重,不保留顺序:
list(set([1, 2, 2, 3, 1]))     # 顺序不稳定
# 保留顺序去重(3.7+ dict 保序):
list(dict.fromkeys([1, 2, 2, 3, 1]))   # [1, 2, 3]

set() 会丢顺序,dict.fromkeys() 保留首次出现顺序(3.7+ dict 保序)。

集合推导式

{x * x for x in range(10)}         # {0, 1, 4, 9, ..., 81}
{w.lower() for w in words}         # 去重 + 小写
# 一句话拿独立词数:
unique_words = len({w.lower() for w in text.split()})

语法和 list / dict 推导一样,用 {} 但没 key:。算"去重总数"一行搞定。

元组 / dataclass (4)

tuple 基础与不可变性

t = (1, 2, 3)
t = 1, 2, 3            # 括号可省,逗号才是关键
single = (1,)          # 单元素元组要加逗号!
empty = ()
# 不可变 —— 不能改:
# t[0] = 99  → TypeError
a, b, c = t            # 拆包

元组靠逗号定义,不是括号。单元素元组要写 (1,) —— (1) 只是数字 1,最常见的坑。

namedtuple 轻量数据结构

from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
p.x, p.y           # 3, 4
p[0]               # 3   (也支持索引)
p._asdict()        # {"x": 3, "y": 4}
Point(**{"x": 5, "y": 6})

namedtuple 给元组加字段名 —— 不可变、轻、能 pickle。要默认值、加方法就改用 dataclass。

dataclass 现代数据类

from dataclasses import dataclass, field
@dataclass
class User:
    name: str
    age: int = 0
    tags: list[str] = field(default_factory=list)   # 可变默认值必须 factory

u = User("Lei", 30)
u.age = 31           # 默认可变
@dataclass(frozen=True)   # 不可变版本
class Point:
    x: float
    y: float

dataclass(3.7+)自动生成 __init__ / __repr__ / __eq__。可变默认值必须 field(default_factory=list),否则中招"可变默认参数"坑。frozen=True 出不可变版本。

tuple 解构与 *rest

a, b, c = (1, 2, 3)
first, *rest = [1, 2, 3, 4]       # 1, [2, 3, 4]
*init, last = [1, 2, 3, 4]        # [1, 2, 3], 4
a, *_, b = range(10)              # 头尾,中间扔掉
# 函数返回多值常用:
def divmod_(a, b):
    return a // b, a % b
q, r = divmod_(10, 3)

解构带 *rest 能接中间或末尾。函数返回多值其实就是返回元组 —— 调用端再解构出来。

控制流 (5)

if / elif / else

if x > 0:
    print("正")
elif x < 0:
    print("负")
else:
    print("零")
# 三元(条件表达式):
label = "正" if x > 0 else "非正"

标准分支。Python 写 elif 不是 else if。三元:值1 if 条件 else 值2 —— 条件在中间,跟 C/JS 不一样。

for / for-else

for x in items:
    if x < 0:
        break
else:
    print("没遇到负数")     # break 没触发才会跑

for i in range(5): print(i)
for i in range(2, 10, 2): print(i)    # 2, 4, 6, 8

for-else:循环没被 break 才会跑 else —— 写"找不到就报告"的逻辑很简洁。

while / break / continue

while queue:
    x = queue.pop(0)
    if x is None:
        continue
    if x == "stop":
        break
    process(x)
# while-else 同样:else 在没 break 时跑

while 条件为真就一直跑。break 跳出整个循环,continue 跳过本次。while-else 也存在,逻辑同 for-else。

match / case(3.10+ 模式匹配)

def http_status(code: int) -> str:
    match code:
        case 200 | 201 | 204:
            return "OK"
        case 301 | 302:
            return "Redirect"
        case 400 | 404:
            return "Client error"
        case n if 500 <= n < 600:    # guard
            return "Server error"
        case _:
            return "Unknown"

# 解构匹配:
match point:
    case (0, 0): return "原点"
    case (x, 0): return f"X 轴 {x}"
    case (0, y): return f"Y 轴 {y}"
    case (x, y): return f"({x},{y})"

3.10+ 才有的结构化模式匹配。| 表示或,case ... if x 是 guard。能匹配元组、字典、类。最后写 case _: 当 default。

walrus := 海象运算符

# 在 while 条件里赋值 + 判断:
while chunk := f.read(4096):
    process(chunk)

# if 里赋值 + 用:
if (n := len(items)) > 10:
    print(f"too many: {n}")

# 推导里复用计算结果:
[y for x in data if (y := expensive(x)) is not None]

海象 := 既赋值又返回。最适合"循环条件里要拿值又要判"和"推导式里要复用计算结果"两种场景。

函数 (8)

def 定义函数 / 默认参数

def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}!"

greet("Lei")                        # "Hello, Lei!"
greet("Lei", greeting="嗨")          # 关键字参数

# 坑:可变默认值(永远不要这样写)
def add(item, items=[]):            # ❌ 所有调用共享同一个 list
    items.append(item)
    return items
def add(item, items=None):          # ✅ 正确写法
    if items is None:
        items = []
    items.append(item)
    return items

默认参数在 def 时求值一次 —— 千万别用 [] 或 {} 这种可变默认值。要用 None 然后在函数里初始化。

lambda 匿名函数

add = lambda a, b: a + b
sorted(rows, key=lambda r: r[1])
list(filter(lambda x: x > 0, nums))
# lambda 只能写单个表达式,不能有 return / for / 多行
# 多行逻辑就老老实实 def

lambda 只能单表达式,不能有语句、不能多行。短回调可以用,逻辑长就老老实实 def。

*args 与 **kwargs

def fn(*args, **kwargs):
    print(args)      # 元组
    print(kwargs)    # 字典
fn(1, 2, 3, name="Lei")
# 转发参数(装饰器常用):
def wrapper(*args, **kwargs):
    return inner(*args, **kwargs)
# 强制关键字参数(* 之后必须 keyword):
def connect(host, *, port=80, ssl=False):
    pass
connect("x", port=443)        # ✅
# connect("x", 443)            # ❌ TypeError

*args 把位置参数收成元组,**kwargs 把关键字参数收成字典。裸 * 强制后面必须 keyword 调用 —— API 设计利器,避免位置参数搞混。

type hint 类型注解

def greet(name: str, times: int = 1) -> str:
    return ("Hi " + name + "! ") * times

from typing import Optional, Union, Callable
def get(key: str) -> Optional[str]: ...
# 3.10+ 简化:
def get(key: str) -> str | None: ...
# 3.9+ 内置泛型:
def parse(items: list[int]) -> dict[str, int]: ...
# 函数类型:
def apply(fn: Callable[[int, int], int], a: int, b: int) -> int:
    return fn(a, b)

type hint 不强制,但 mypy / pyright 会检查。3.9+ 可以直接写 list[int]、dict[str, int];3.10+ 用 X | Y 替代 Union。

装饰器 decorator

from functools import wraps
import time
def timed(fn):
    @wraps(fn)                    # 保留 fn 的 __name__ / docstring
    def inner(*args, **kwargs):
        t = time.perf_counter()
        result = fn(*args, **kwargs)
        print(f"{fn.__name__} took {time.perf_counter()-t:.3f}s")
        return result
    return inner

@timed
def slow():
    time.sleep(1)

装饰器是接受函数、返回函数的函数。一定要用 @functools.wraps 保留原函数的 __name__ 和 docstring,否则反射全废。

闭包与 late binding 坑

# 经典 late binding 坑:
fns = [lambda: i for i in range(3)]
[f() for f in fns]            # [2, 2, 2],不是 [0, 1, 2]
# 修复:默认参数当时绑定
fns = [lambda i=i: i for i in range(3)]
[f() for f in fns]            # [0, 1, 2]

循环里的 lambda 按引用捕获变量,不是按值 —— 最后全看到末值。修复:写 lambda i=i: i,用默认参数把当前值固定下来。

global 与 nonlocal

count = 0
def inc():
    global count        # 不写就报 UnboundLocalError
    count += 1

def make_counter():
    n = 0
    def inc():
        nonlocal n      # 修改外层函数的 n(不是 global)
        n += 1
        return n
    return inc

函数内读外层变量 OK,但要赋值必须声明 global(模块级)或 nonlocal(外层函数)—— 不然就抛 UnboundLocalError。

partial 预绑定参数

from functools import partial
def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
cube = partial(power, exp=3)
square(5)        # 25
cube(3)          # 27

# 实战:给 sorted 传带固定参数的 key
sorted(rows, key=partial(getattr, default=None))

partial 把一部分参数预先绑死,返回新可调用。比写 lambda 干净,专门用于参数固定的场景。

(7)

class 基础 / __init__ / self

class User:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def greet(self) -> str:
        return f"Hi, I'm {self.name}"

u = User("Lei", 30)
u.greet()

__init__ 是创建实例后的初始化。self 是当前实例 —— 约定俗成,但每个方法定义都必须显式带上。

@property 优雅封装

class Circle:
    def __init__(self, r):
        self.r = r
    @property
    def area(self):
        return 3.14159 * self.r ** 2
    @area.setter
    def area(self, value):
        self.r = (value / 3.14159) ** 0.5

c = Circle(5)
c.area          # 不用 c.area(),直接像属性一样访问
c.area = 100    # 触发 setter

@property 把方法变成属性访问。@prop.setter 定义写入逻辑。需要校验或派生时用,比 getter/setter 函数地道。

@classmethod / @staticmethod

class User:
    def __init__(self, name):
        self.name = name
    @classmethod
    def from_dict(cls, d):       # 工厂方法
        return cls(d["name"])
    @staticmethod
    def is_valid_name(s):        # 与类相关但不需要 cls / self
        return s.isalpha()

u = User.from_dict({"name": "Lei"})
User.is_valid_name("Lei")

classmethod 接收 cls(类本身),用于工厂方法。staticmethod 啥都不接收,是放在类命名空间里的工具函数。

dunder methods 让对象像内置类型

class Money:
    def __init__(self, amount, currency):
        self.amount = amount
        self.currency = currency
    def __repr__(self):
        return f"Money({self.amount}, '{self.currency}')"
    def __str__(self):
        return f"{self.amount:.2f} {self.currency}"
    def __eq__(self, other):
        return (self.amount, self.currency) == (other.amount, other.currency)
    def __hash__(self):
        return hash((self.amount, self.currency))
    def __lt__(self, other):
        return self.amount < other.amount
    def __add__(self, other):
        return Money(self.amount + other.amount, self.currency)

__repr__ 给调试看,__str__ 给用户看;__eq__/__hash__ 让对象能进 set / dict 当 key;__lt__ 让 sorted() 能排;__add__ 让 + 工作。

继承与 super

class Animal:
    def __init__(self, name):
        self.name = name
    def speak(self):
        return "..."

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)        # 调父类 __init__
        self.breed = breed
    def speak(self):                  # 覆盖
        return "Woof!"

继承写 class Sub(Base)。super().method() 调父类。多继承按 MRO(方法解析顺序)。

@dataclass + frozen + slots

from dataclasses import dataclass

@dataclass(frozen=True, slots=True)    # 3.10+ slots=True
class Point:
    x: float
    y: float

p = Point(3, 4)
# p.x = 99   → FrozenInstanceError   不可变
# p.z = 99   → AttributeError        slots 禁止新属性
hash(p)      # frozen=True 自动可哈希

frozen=True 让实例不可变且可哈希。slots=True(3.10+)用 __slots__ 省内存,且能防止打错字新建属性。

自定义 with 上下文

class Timer:
    def __enter__(self):
        import time
        self.t = time.perf_counter()
        return self
    def __exit__(self, exc_type, exc, tb):
        import time
        print(f"耗时 {time.perf_counter() - self.t:.3f}s")
        return False     # False / None 表示不吞异常

with Timer():
    slow_op()

# 或用 @contextmanager 装饰生成器:
from contextlib import contextmanager
@contextmanager
def open_db():
    conn = connect()
    try:
        yield conn
    finally:
        conn.close()

类实现 __enter__/__exit__,或更简单:写生成器 + @contextmanager。清理逻辑放 finally / __exit__ 才稳。

文件 / IO (5)

open 与 with 读写文件

# 读文本(自动指定 encoding,别依赖系统默认!)
with open("a.txt", "r", encoding="utf-8") as f:
    content = f.read()

# 一行行读(大文件友好,不全部加载)
with open("big.log", encoding="utf-8") as f:
    for line in f:
        process(line.rstrip("\n"))

# 写文本
with open("out.txt", "w", encoding="utf-8") as f:
    f.write("hello\n")
    f.writelines(["a\n", "b\n"])

# 追加
with open("out.txt", "a", encoding="utf-8") as f:
    f.write("more\n")

# 二进制
with open("img.png", "rb") as f:
    data = f.read()

永远用 with 打开 —— 出异常也会关。永远显式传 encoding="utf-8",别依赖系统默认(不同系统差异巨大,Windows 默认 cp936 害死人)。

pathlib 现代路径操作

from pathlib import Path
p = Path("data") / "users" / "lei.json"   # / 操作符拼路径
p.exists()
p.is_file(), p.is_dir()
p.parent, p.name, p.stem, p.suffix
p.read_text(encoding="utf-8")
p.write_text("hello", encoding="utf-8")
list(Path(".").glob("*.py"))              # 通配
list(Path(".").rglob("*.py"))             # 递归
Path("out").mkdir(parents=True, exist_ok=True)

pathlib(3.4+)用 Path 对象替代 os.path 字符串拼接。用 / 拼路径 —— 永远别字符串相加或 os.path.join。

json 读写 JSON

import json

# 字符串 ↔ 对象
data = json.loads('{"a": 1}')
s = json.dumps({"a": 1})                   # 紧凑
s = json.dumps(obj, indent=2, ensure_ascii=False)   # 缩进 + 中文不转义

# 文件 ↔ 对象
with open("data.json", encoding="utf-8") as f:
    data = json.load(f)
with open("out.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=2, ensure_ascii=False)

load/dump 操作文件,loads/dumps 操作字符串。有中文一定加 ensure_ascii=False,否则全变成 \u 转义。

csv 读写 CSV

import csv

# 读
with open("data.csv", encoding="utf-8", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row["name"], row["age"])

# 写
with open("out.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["name", "age"])
    writer.writeheader()
    writer.writerow({"name": "Lei", "age": 30})

CSV 文件打开一定加 newline="",否则 Windows 会插空行。DictReader / DictWriter 自动处理表头。

tempfile 临时文件 / 目录

import tempfile
# 临时文件(自动删除):
with tempfile.NamedTemporaryFile(mode="w", suffix=".txt", delete=False) as f:
    f.write("data")
    path = f.name

# 临时目录:
with tempfile.TemporaryDirectory() as d:
    p = Path(d) / "x.txt"
    p.write_text("hi")
    # 出 with 时 d 整个被删

tempfile 让 OS 管理临时路径。NamedTemporaryFile / TemporaryDirectory 出 with 自动清理,省心。

异常 (4)

try / except / else / finally

try:
    n = int(s)
    data = fetch(n)
except ValueError as e:
    print(f"输入不是数字: {e}")
except (KeyError, IndexError) as e:    # 多种异常一起
    print(f"数据问题: {e}")
except Exception as e:                  # 兜底
    print(f"其他错误: {e}")
    raise                                # 抛出去
else:
    print("没出错才跑这里")
finally:
    cleanup()                            # 出不出错都跑

else 只有没出异常才跑。finally 不管有没有异常都跑(清理)。裸 except: 会吞掉 Ctrl+C —— 几乎永远是错的,要用 except Exception:。

raise 抛异常 / 链式异常

raise ValueError("age 不能为负")
raise ValueError(f"非法值 {x}")

# 包装别人的异常(保留原始 traceback)
try:
    int(s)
except ValueError as e:
    raise ParseError("解析失败") from e

# 想隐藏原始链:
raise ParseError("...") from None

raise X from Y 包装 Y 异常并保留链 —— traceback 两层都看得到。raise X from None 隐藏原始(很少需要)。

自定义异常

class APIError(Exception):
    """所有 API 错误的基类"""

class RateLimitError(APIError):
    def __init__(self, retry_after: int):
        super().__init__(f"rate limited, retry after {retry_after}s")
        self.retry_after = retry_after

try:
    call_api()
except RateLimitError as e:
    time.sleep(e.retry_after)
except APIError:
    log.exception("api failed")

每个包定义一个基类异常,再派生子类 —— 调用方能选择抓"全家族"或具体类型。继承 Exception,不要继承 BaseException。

contextlib.suppress 优雅忽略

from contextlib import suppress

# 老写法:
try:
    os.remove("not-exist.txt")
except FileNotFoundError:
    pass

# 新写法:
with suppress(FileNotFoundError):
    os.remove("not-exist.txt")

# 多个异常:
with suppress(KeyError, IndexError):
    value = data["k"][0]

suppress(异常类型) 静默吞掉指定异常 —— 一行操作要忽略错误时比 try/except/pass 干净。

迭代器 / 生成器 (6)

iter / next 迭代器协议

it = iter([1, 2, 3])
next(it)      # 1
next(it)      # 2
next(it)      # 3
next(it)      # StopIteration
next(it, "默认")    # 第二个参数避免 StopIteration

# 任何实现 __iter__ + __next__ 的对象都是迭代器
class CountUp:
    def __init__(self, n): self.n = n; self.i = 0
    def __iter__(self): return self
    def __next__(self):
        if self.i >= self.n: raise StopIteration
        self.i += 1
        return self.i

iter(obj) 拿迭代器,next(it) 推进。next(it, 默认) 安全版避免 StopIteration。for 循环背后就是在调这两个。

generator / yield 惰性生成

def count_up(n):
    i = 0
    while i < n:
        yield i        # 每次 yield 暂停,下次 next() 继续
        i += 1

for x in count_up(5): print(x)
# 生成器表达式(节省内存):
squares = (x * x for x in range(1_000_000))
sum(squares)

yield 让函数变生成器 —— 惰性产值、状态保留。生成器表达式用 () 不是 [] —— 处理超大数据时省内存。

yield from 委托子生成器

def flatten(nested):
    for item in nested:
        if isinstance(item, list):
            yield from flatten(item)    # 递归
        else:
            yield item

list(flatten([1, [2, [3, [4]]], 5]))    # [1, 2, 3, 4, 5]

yield from 把迭代委托给另一个可迭代对象,含其所有子 yield。比手写 for + yield 简洁。

itertools 常用

from itertools import chain, groupby, permutations, combinations, product, accumulate, islice
list(chain([1, 2], [3, 4]))                    # [1, 2, 3, 4]
list(chain.from_iterable([[1, 2], [3, 4]]))    # [1, 2, 3, 4]
list(permutations([1, 2, 3], 2))               # 排列 (1,2),(1,3),(2,1)...
list(combinations([1, 2, 3], 2))               # 组合 (1,2),(1,3),(2,3)
list(product([0, 1], repeat=3))                # 笛卡尔积
list(accumulate([1, 2, 3, 4]))                 # [1, 3, 6, 10] 前缀和
list(islice(big_iter, 10))                     # 取前 10 个

# groupby 必须先排序!
rows = sorted(rows, key=itemgetter("group"))
for g, items in groupby(rows, key=itemgetter("group")):
    print(g, list(items))

itertools 是标准库的迭代器工具箱。最大的坑:groupby 只合并连续相等的元素,用之前必须先按 key 排序。

functools.reduce / lru_cache

from functools import reduce, lru_cache, cache
reduce(lambda a, b: a + b, [1, 2, 3, 4])     # 10
reduce(lambda a, b: a + b, [1, 2, 3, 4], 100)  # 110 (初值)

@lru_cache(maxsize=None)                      # 自动记忆
def fib(n):
    return n if n < 2 else fib(n-1) + fib(n-2)

@cache     # 3.9+ 简化版 lru_cache(maxsize=None)
def f(x): ...

reduce 把二元运算累折叠。@lru_cache 自动记忆,能把指数递归变线性。@cache(3.9+)是 lru_cache(maxsize=None) 的简写。

zip_longest / takewhile / dropwhile

from itertools import zip_longest, takewhile, dropwhile
list(zip_longest([1, 2], ["a", "b", "c"], fillvalue="-"))
# [(1, 'a'), (2, 'b'), ('-', 'c')]   长度对不齐用 fillvalue 填
list(takewhile(lambda x: x < 5, [1, 3, 4, 6, 2]))   # [1, 3, 4]   遇到 False 就停
list(dropwhile(lambda x: x < 5, [1, 3, 4, 6, 2]))   # [6, 2]      跳到第一个 False

zip_longest 用 fillvalue 补齐短的一边。takewhile / dropwhile 在第一个不满足条件处切开 —— 处理流式数据特别合适。

异步 (5)

async / await 基础

import asyncio

async def fetch(url):
    await asyncio.sleep(1)         # 模拟 IO
    return f"data from {url}"

async def main():
    data = await fetch("https://x.com")
    print(data)

asyncio.run(main())                # 入口必须这一行

async def 定义协程,await 让出控制权。asyncio.run() 是入口 —— 已经在事件循环里就不能再 run,会报错。

asyncio.gather 并发执行

async def main():
    urls = ["a", "b", "c"]
    # 串行(慢):
    results = [await fetch(u) for u in urls]
    # 并发(快 N 倍):
    results = await asyncio.gather(*[fetch(u) for u in urls])
    # 一个失败别全部炸:
    results = await asyncio.gather(*tasks, return_exceptions=True)
    # 3.11+ TaskGroup(推荐写法,更安全):
    async with asyncio.TaskGroup() as tg:
        ts = [tg.create_task(fetch(u)) for u in urls]
    results = [t.result() for t in ts]

gather 并发跑多个协程。return_exceptions=True 让一个失败不连累其他。3.11+ TaskGroup 是更安全的现代写法,异常处理更干净。

asyncio.create_task / wait / timeout

# 立刻调度,不等:
task = asyncio.create_task(fetch("x"))
# 之后再 await:
result = await task

# 限时:3.11+
async with asyncio.timeout(5):
    await long_op()
# 旧写法 3.10-:
try:
    await asyncio.wait_for(long_op(), timeout=5)
except asyncio.TimeoutError:
    ...

# 等任一个完成:
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)

create_task 立刻调度。asyncio.timeout(3.11+)用 async with 包裹做超时;老代码用 wait_for。

async for / async with

# 异步迭代器
async def fetch_pages():
    async for chunk in client.stream("..."):
        yield chunk

# 异步上下文管理
async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
        text = await resp.text()

async for / async with 用于实现了 __aiter__ / __aenter__ 的对象 —— HTTP 客户端、数据库驱动、流文件常见。

asyncio.Queue / Semaphore 并发原语

# Semaphore 限并发:
sem = asyncio.Semaphore(10)
async def fetch_limited(url):
    async with sem:
        return await fetch(url)

# Queue 生产消费:
q = asyncio.Queue(maxsize=100)
async def producer():
    for x in items:
        await q.put(x)
    await q.put(None)        # 哨兵
async def consumer():
    while (x := await q.get()) is not None:
        process(x)
        q.task_done()

Semaphore 限并发数(比如 HTTP 同时只跑 10 个)。Queue 是生产消费模型,用 None 当哨兵告诉消费者结束。

类型提示 (7)

typing 基础

# 3.8 写法(typing 模块):
from typing import List, Dict, Tuple, Set
def fn(xs: List[int], d: Dict[str, int]) -> Tuple[int, ...]: ...

# 3.9+ 推荐用内置(不用 import):
def fn(xs: list[int], d: dict[str, int]) -> tuple[int, ...]: ...

# tuple 长度固定写法:
Tuple[int, str, float]   # 三元素,类型不同
tuple[int, ...]          # 任意长度,元素都是 int

3.9+ 可直接用 list[int] / dict[str, int] / set[X],不用 from typing import 了。typing 的别名(List/Dict)还能用但不必。

Optional / Union / None

from typing import Optional, Union
def get(k: str) -> Optional[str]: ...    # str 或 None
def x(v: Union[int, str]): ...           # int 或 str

# 3.10+ 推荐用 | :
def get(k: str) -> str | None: ...
def x(v: int | str): ...

# Optional[T] === T | None
# 它不是"可省略",而是"可能为 None",别误解

Optional[T] 是"可能为 None",不是"可省略参数" —— 别误解。3.10+ 用 T | None / int | str 替代,更短。

TypedDict 结构化字典

from typing import TypedDict, NotRequired

class User(TypedDict):
    name: str
    age: int
    email: NotRequired[str]     # 3.11+

def greet(u: User) -> str:
    return f"Hi, {u['name']}"

greet({"name": "Lei", "age": 30})           # ✅
# greet({"name": "Lei"})                     # mypy 报错:缺 age

TypedDict 给字典形状加类型 —— JSON 风格数据特别适合,不用写整个类。3.11+ 的 NotRequired / Required 支持可选键。

Protocol 鸭子类型 + 静态检查

from typing import Protocol

class HasName(Protocol):
    name: str
    def greet(self) -> str: ...

def shout(x: HasName) -> str:
    return x.greet().upper()

# 任何有 name 属性 + greet() 方法的对象都满足 HasName
# 不用继承,结构匹配即可(structural typing)

Protocol(3.8+)是带静态检查的鸭子类型 —— 形状对就算实现,不用继承。Python 版的 Go interface。

Generic / TypeVar 泛型

from typing import TypeVar, Generic
T = TypeVar("T")

def first(xs: list[T]) -> T:
    return xs[0]

class Stack(Generic[T]):
    def __init__(self): self._items: list[T] = []
    def push(self, x: T): self._items.append(x)
    def pop(self) -> T: return self._items.pop()

# 3.12+ 新语法(不用 TypeVar):
def first[T](xs: list[T]) -> T:
    return xs[0]

TypeVar 声明泛型参数。Generic[T] 让类支持泛型。3.12+ 新语法更简洁:def f[T](xs: list[T])。

Literal / Final / Annotated

from typing import Literal, Final, Annotated
def open_file(mode: Literal["r", "w", "rb", "wb"]): ...
open_file("r")     # ✅
# open_file("x")   # mypy 报错

MAX: Final = 100             # 不可重新赋值
PI: Final[float] = 3.14159

# Annotated 给类型加元数据(pydantic / fastapi 常用):
Age = Annotated[int, "0-150"]

Literal 限定具体字面量 —— 模式参数特别好用。Final 标常量。Annotated 给类型加元数据,Pydantic / FastAPI 会读。

cast / overload 类型断言与重载

from typing import cast, overload

# 告诉类型检查器"我知道这里是什么"
x = cast(int, obj["count"])      # 运行时啥都不做,只骗 mypy

# 函数重载(多个签名,一份实现):
@overload
def fetch(x: int) -> User: ...
@overload
def fetch(x: str) -> list[User]: ...
def fetch(x):
    # 真实实现
    return _do(x)

cast() 只骗 mypy,运行时啥都不做。@overload 声明多重签名(一份实现),适合返回类型随入参类型变的函数。

常见坑 (9)

可变默认参数

# ❌ 错误(所有调用共享同一个 list):
def add(item, items=[]):
    items.append(item)
    return items
add(1)            # [1]
add(2)            # [1, 2]   不是 [2]!

# ✅ 正确:
def add(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

默认参数在 def 时求值一次,[] / {} / set() 这种可变默认值会被所有调用共享 —— 调用间累积。永远用 None 哨兵 + 函数内初始化。

late binding 闭包

# ❌ 全是 2:
fns = [lambda: i for i in range(3)]
[f() for f in fns]      # [2, 2, 2]

# ✅ 默认参数当时固定:
fns = [lambda i=i: i for i in range(3)]
[f() for f in fns]      # [0, 1, 2]

闭包按变量捕获不按值捕获 —— 所有 lambda 看到的都是末值。用 lambda i=i: 把当前值冻在默认参数里。

浅拷贝 vs 深拷贝

import copy
a = [[1, 2], [3, 4]]
b = a              # 同一个对象(引用)
b = a[:]           # 浅拷贝:外层新,内层共享
b = a.copy()       # 浅拷贝
b = copy.copy(a)   # 浅拷贝
b = copy.deepcopy(a)   # 深拷贝(递归)

a[0].append(99)
print(b)           # 浅拷贝下 b 也变了!

切片 / .copy() / copy.copy() 都是浅拷贝,内层对象共享。copy.deepcopy() 递归克隆整棵树。要不要深拷贝看内部对象会不会被修改。

is vs ==

a = [1, 2, 3]
b = [1, 2, 3]
a == b      # True   值相等
a is b      # False  不是同一个对象

# is 只对单例可靠:None / True / False / 小整数缓存等
x is None   # ✅ 推荐
x == None   # 能跑,不地道

# 坑:小整数缓存(-5 到 256)
a = 256; b = 256
a is b      # True  (缓存)
a = 257; b = 257
a is b      # 一般是 False

is 比身份(同一对象),== 比值。只对 None / True / False 这种单例用 is。小整数缓存(-5~256)是 CPython 实现细节,永远别依赖。

遍历时修改容器

# ❌ 边遍历边删 —— RuntimeError 或漏删
for x in list_:
    if x.bad:
        list_.remove(x)

# ✅ 倒序删 / 或新建一个:
for i in range(len(list_) - 1, -1, -1):
    if list_[i].bad:
        del list_[i]

xs = [x for x in xs if not x.bad]    # 最地道

# dict 也同样:
for k in list(d.keys()):     # list() 拷一份再删
    if d[k] is None:
        del d[k]

边遍历边删容器会漏元素或抛 RuntimeError。要么先 list() 拷一份再遍历,要么用推导式新建一个。

global / nonlocal 不写就报错

count = 0
def inc():
    count += 1            # ❌ UnboundLocalError
                          # 因为函数里赋值了 count,Python 把它当本地变量

def inc():
    global count          # ✅ 显式声明
    count += 1

函数里任何地方给 count 赋值,Python 就认它是本地变量(哪怕在赋值前用也算)—— 不写 global / nonlocal 就 UnboundLocalError。

整数除法 / vs //

7 / 2      # 3.5      (Python 3 一律返回 float)
7 // 2     # 3        整除
-7 // 2    # -4       向下取整(不是向 0 取整!)
divmod(7, 2)   # (3, 1)   商和余数一起

# 来自 Python 2 的代码可能假设 / 是整除 —— 升 3 时小心

Python 3 中 / 一律返回 float,// 是向下取整(不是向 0 取整:-7 // 2 是 -4 不是 -3)。divmod() 同时给商和余数。

字符串拼接性能陷阱

# ❌ O(n²) — 字符串不可变,每次 + 都拷贝整段
s = ""
for x in items:
    s += str(x)

# ✅ O(n) — 收集再 join
parts = []
for x in items:
    parts.append(str(x))
s = "".join(parts)

# 或者列表推导 + join:
s = "".join(str(x) for x in items)

字符串不可变,循环里 s += x 是 O(n²)(每次拷贝整段)。先收集到 list 再 "".join() 是 O(n) —— 大数据量差距巨大。

裸 except 是坑

# ❌ 吞掉 KeyboardInterrupt 和 SystemExit
try:
    risky()
except:
    pass

# ✅ 抓 Exception 就够了
try:
    risky()
except Exception as e:
    log.exception(e)

裸 except 会抓 BaseException —— 连 Ctrl+C 和 sys.exit 都吞了。要用 except Exception: 抓正常错误就行。

这个工具能做什么

可搜索的 Python 速查表,覆盖日常真在撸的 100+ 段地道 代码,不是凑数的 hello-world 入门列表。十五大分类: 基础(赋值与拆包、int/float/Decimal、bool 真假值、 None 单例、isinstance、range),字符串(f-string 含 格式说明符、split/join、strip 系列、replace 与 re.sub、 切片、UTF-8 编解码),列表(append vs extend 坑、list 推导含过滤和三元、sorted 带 key 稳定排序、enumerate、 zip 与 strict、保序去重),字典(.get 链式取值、 setdefault vs defaultdict、3.9 | 合并、Counter),集 合(| & - ^ 做并交差对称差、frozenset 可哈希、推导式 去重),元组(单元素逗号坑、namedtuple、dataclass 与 field(default_factory)、*rest 解构),控制流(if/ elif、for-else、while、海象 :=、3.10 match/case 含 guard 和解构),函数(默认参数坑、lambda 限制、*args/ **kwargs 与 keyword-only、type hint、@decorator 配 functools.wraps、partial),类(__init__、@property setter、@classmethod / @staticmethod、dunder 方法、 super 与 MRO、@dataclass frozen + slots、__enter__/ __exit__),文件(open 必加 encoding="utf-8"、pathlib 的 / 拼接、json 必加 ensure_ascii=False、csv 必加 newline=""、tempfile),异常(try/except/else/finally、 raise from、自定义异常继承、contextlib.suppress),迭 代(next 带默认、yield 生成器、yield from、itertools chain/groupby/permutations/accumulate、functools.reduce / @lru_cache、zip_longest / takewhile),异步(asyncio. run、gather 加 return_exceptions、create_task/timeout、 async for / async with、Queue + Semaphore、3.11 TaskGroup),类型提示(3.9 list[int]、3.10 X | None、 TypedDict + NotRequired、Protocol 鸭子接口、TypeVar / Generic、Literal / Final、cast / @overload),以及 9 个真烧时间的坑(可变默认参数、late binding 闭包、浅 拷贝 vs 深拷贝、is vs ==、遍历时修改容器、 UnboundLocalError、裸 except 吞 Ctrl+C、-7 // 2 是 -4、循环里字符串拼接 O(n²))。每条都带:双语标题、 可直接复制的真实代码、双语说明、1-2 条变式。搜索框 跨标题 / 代码 / 说明 / 变式四字段一起过滤,分类胶囊 缩范围,一键复制。完全在浏览器里跑,不连任何服务、 不上传。配合 SQL / curl / git / regex 速查覆盖整条 技术栈,搭 JSON Formatter 处理数据。

工具细节

输入
文件
页面会根据工具类型展示文本框、数值控件、文件选择或结构化输入。
输出
即时结果 + 复制
结果区优先给出可操作结果,支持项会显示复制、下载或可视化预览。
隐私
可能使用网络查询
组件源码里检测到网络调用,页面会按工具逻辑处理;敏感内容建议先脱敏。
保存 / 分享
免账号使用
打开页面即可使用;刷新后是否保留结果取决于具体工具。
性能预算
首屏 JS ≤ 30 KB
没有声明 WASM 依赖,适合快速打开和移动端使用。
适用场景
开发运维 · 程序员
分类和职业标签用于推荐相关工具、组织内链,并帮助用户快速判断是否适合当前任务。

怎么用

  1. 1. 输入

    把内容粘贴或拖入工具面板。

  2. 2. 处理

    点击按钮,在浏览器内本地处理,文件不上传。

  3. 3. 复制 / 下载

    一键复制结果或下载到本地。

Python 速查表 适合怎么用

适合穿插在写代码、查问题、做 Review、上线前的小任务里。

适合开发场景

  • 格式化、校验、压缩或检查和代码相关的文本。
  • 把片段整理好再放进文档、工单、提交或交接材料。
  • 不切换工具,快速检查一个小 payload。

开发检查项

  • 压缩、混淆这类不可逆处理,先对副本操作。
  • 除非确认工具本地处理,不要粘贴密钥和敏感片段。
  • 转换后的代码上线前,仍要跑自己的测试或 lint。

下一步可以接着做

这些入口会把当前任务接到更完整的工具链里。

  1. 1 JSON 格式化与校验 浏览器内即时格式化、校验、压缩 JSON,数据不离开本地。 打开
  2. 2 SQL 速查表 SQL 速查表,100+ 条覆盖 SELECT、JOIN、窗口函数、索引,含 MySQL/PostgreSQL/SQLite 方言差异。 打开
  3. 3 curl 命令速查 curl 命令速查,80+ 条覆盖 GET/POST/认证/上传/下载/SSL/代理,真实例子和常见坑。 打开

常见问题

类似工具组合

做你这行的人, 还会一起用这些。

Made by Toolora · 100% client-side · Updated 2026-05-29