目录
第一部分:基础错误(按出现频率排序)
- [1. 语法错误 (SyntaxError)](#1. 语法错误 (SyntaxError))
- [2. 名称错误 (NameError)](#2. 名称错误 (NameError))
- [3. 类型错误 (TypeError)](#3. 类型错误 (TypeError))
- [4. 值错误 (ValueError)](#4. 值错误 (ValueError))
- [5. 索引错误 (IndexError)](#5. 索引错误 (IndexError))
- [6. 键错误 (KeyError)](#6. 键错误 (KeyError))
- [7. 属性错误 (AttributeError)](#7. 属性错误 (AttributeError))
- [8. 导入错误 (ImportError/ModuleNotFoundError)](#8. 导入错误 (ImportError/ModuleNotFoundError))
- [9. 缩进错误 (IndentationError)](#9. 缩进错误 (IndentationError))
- [10. 除零错误 (ZeroDivisionError)](#10. 除零错误 (ZeroDivisionError))
第二部分:文件和系统错误
- [11. 文件错误 (FileNotFoundError)](#11. 文件错误 (FileNotFoundError))
- [12. 权限错误 (PermissionError)](#12. 权限错误 (PermissionError))
- [13. 路径错误 (OSError)](#13. 路径错误 (OSError))
第三部分:运行时错误
- [14. 递归错误 (RecursionError)](#14. 递归错误 (RecursionError))
- [15. 编码错误 (UnicodeError)](#15. 编码错误 (UnicodeError))
- [16. 内存错误 (MemoryError)](#16. 内存错误 (MemoryError))
- [17. 溢出错误 (OverflowError)](#17. 溢出错误 (OverflowError))
- [18. 未绑定局部变量错误 (UnboundLocalError)](#18. 未绑定局部变量错误 (UnboundLocalError))
第四部分:面向对象错误
- [19. 类和对象错误](#19. 类和对象错误)
- [20. 继承相关错误](#20. 继承相关错误)
第五部分:逻辑和语义错误
- [21. 逻辑错误](#21. 逻辑错误)
- [22. 作用域和闭包错误](#22. 作用域和闭包错误)
- [23. 比较运算错误](#23. 比较运算错误)
- [24. 布尔运算错误](#24. 布尔运算错误)
第六部分:数据结构错误
- [25. 列表操作错误](#25. 列表操作错误)
- [26. 字典操作错误](#26. 字典操作错误)
- [27. 字符串操作错误](#27. 字符串操作错误)
- [28. 集合操作错误](#28. 集合操作错误)
- [29. 切片操作错误](#29. 切片操作错误)
第七部分:高级特性错误
- [30. 迭代器和生成器错误](#30. 迭代器和生成器错误)
- [31. 装饰器错误](#31. 装饰器错误)
- [32. 异常处理错误](#32. 异常处理错误)
- [33. 上下文管理器错误](#33. 上下文管理器错误)
第八部分:现代Python特性错误
- [34. JSON操作错误](#34. JSON操作错误)
- [35. None类型错误](#35. None类型错误)
- [36. 三元运算符错误](#36. 三元运算符错误)
- [37. f-string格式化错误](#37. f-string格式化错误)
- [38. 环境和路径错误](#38. 环境和路径错误)
- [39. 列表推导式高级错误](#39. 列表推导式高级错误)
- [40. 类型转换错误](#40. 类型转换错误)
第九部分:特殊场景错误
- [41. import错误](#41. import错误)
- [42. 数值计算错误](#42. 数值计算错误)
- [43. 日期时间错误](#43. 日期时间错误)
- [44. 正则表达式错误](#44. 正则表达式错误)
第十部分:性能和优化
- [45. 性能问题](#45. 性能问题)
附录
1. 语法错误
错误1: 缺少冒号
错误信息:
SyntaxError: invalid syntax
错误代码:
python
if x > 10
print("大于10")
原因: if语句后缺少冒号
解决方案:
python
if x > 10:
print("大于10")
记忆口诀: if、for、while、def、class后面要冒号
错误2: 括号不匹配
错误信息:
SyntaxError: invalid syntax
或
SyntaxError: unexpected EOF while parsing
错误代码:
python
print("Hello World"
result = (1 + 2 * 3
解决方案:
python
print("Hello World")
result = (1 + 2) * 3
检查技巧:
- 使用IDE的括号匹配高亮功能
- 每写一个左括号,立即写右括号
错误3: 引号不匹配
错误信息:
SyntaxError: EOL while scanning string literal
错误代码:
python
message = "Hello World'
text = 'It's a book"
解决方案:
python
message = "Hello World"
text = "It's a book" # 或 'It\'s a book'
错误4: 等号使用错误
错误信息:
SyntaxError: invalid syntax
错误代码:
python
if x = 10: # 错误:使用了赋值运算符
print("x是10")
解决方案:
python
if x == 10: # 正确:使用比较运算符
print("x是10")
记住:
=是赋值==是比较
错误5: 非法变量名
错误信息:
SyntaxError: invalid syntax
错误代码:
python
2name = "Alice" # 不能以数字开头
my-var = 10 # 不能包含连字符
class = "Python" # 不能使用关键字
解决方案:
python
name2 = "Alice"
my_var = 10
class_name = "Python"
2. 名称错误
错误6: 变量未定义
错误信息:
NameError: name 'variable_name' is not defined
错误代码:
python
print(mesage) # 拼写错误
print(result) # 使用前未定义
解决方案:
python
message = "Hello"
print(message)
result = 10
print(result)
常见原因:
- 变量名拼写错误
- 变量在使用前未定义
- 作用域问题(在函数外使用局部变量)
错误7: 函数名拼写错误
错误信息:
NameError: name 'pirnt' is not defined
错误代码:
python
pirnt("Hello") # print拼写错误
解决方案:
python
print("Hello")
预防方法:
- 使用IDE的自动补全功能
- 开启拼写检查
3. 类型错误
错误8: 字符串和数字拼接
错误信息:
TypeError: can only concatenate str (not "int") to str
错误代码:
python
age = 25
message = "我今年" + age + "岁"
解决方案:
python
# 方法1: 转换为字符串
age = 25
message = "我今年" + str(age) + "岁"
# 方法2: 使用f-string (推荐)
message = f"我今年{age}岁"
# 方法3: 使用format
message = "我今年{}岁".format(age)
错误9: 不支持的操作类型
错误信息:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
错误代码:
python
result = 10 + "5"
解决方案:
python
# 数字加法
result = 10 + int("5") # 15
# 字符串拼接
result = str(10) + "5" # "105"
错误10: 函数参数错误
错误信息:
TypeError: function() takes 2 positional arguments but 3 were given
错误代码:
python
def add(a, b):
return a + b
result = add(1, 2, 3) # 传了3个参数,但只定义了2个
解决方案:
python
def add(a, b):
return a + b
result = add(1, 2) # 正确
# 或者使用可变参数
def add(*args):
return sum(args)
result = add(1, 2, 3) # 可以传任意数量的参数
错误11: 不可调用对象
错误信息:
TypeError: 'int' object is not callable
错误代码:
python
number = 10
result = number(5) # 试图调用一个整数
常见场景:
python
# 场景1: 变量名覆盖了函数名
list = [1, 2, 3] # list变成了列表,不再是函数
numbers = list(range(5)) # 错误!
# 解决方案
my_list = [1, 2, 3]
numbers = list(range(5)) # 正确
# 场景2: 忘记方法调用的括号
text = "hello"
upper_text = text.upper # 错误:缺少括号
upper_text = text.upper() # 正确
4. 值错误
错误12: 类型转换失败
错误信息:
ValueError: invalid literal for int() with base 10: 'abc'
错误代码:
python
number = int("abc")
number = int("3.14")
解决方案:
python
# 使用try-except处理
try:
number = int(input("请输入数字:"))
except ValueError:
print("输入无效,请输入整数")
number = 0
# 先验证再转换
text = "3.14"
if text.isdigit():
number = int(text)
else:
number = int(float(text)) # 先转float再转int
错误13: 解包值数量不匹配
错误信息:
ValueError: too many values to unpack (expected 2)
ValueError: not enough values to unpack (expected 3, got 2)
错误代码:
python
a, b = [1, 2, 3] # 3个值,只有2个变量
x, y, z = [1, 2] # 2个值,但有3个变量
解决方案:
python
# 方法1: 匹配数量
a, b, c = [1, 2, 3]
# 方法2: 使用*接收多余值
a, b, *rest = [1, 2, 3, 4, 5]
print(rest) # [3, 4, 5]
# 方法3: 使用_忽略值
a, b, _ = [1, 2, 3]
5. 索引错误
错误14: 列表索引超出范围
错误信息:
IndexError: list index out of range
错误代码:
python
my_list = [1, 2, 3]
print(my_list[3]) # 索引3不存在(0,1,2)
print(my_list[10])
解决方案:
python
my_list = [1, 2, 3]
# 方法1: 检查长度
if len(my_list) > 3:
print(my_list[3])
# 方法2: 使用try-except
try:
print(my_list[3])
except IndexError:
print("索引不存在")
# 方法3: 使用负索引访问最后元素
print(my_list[-1]) # 3(最后一个)
# 方法4: 使用切片(不会报错)
print(my_list[3:]) # [] 空列表
常见陷阱:
python
# 循环中的索引错误
numbers = [1, 2, 3, 4, 5]
# 错误
for i in range(len(numbers) + 1):
print(numbers[i]) # 最后一次会越界
# 正确
for i in range(len(numbers)):
print(numbers[i])
# 更好:直接遍历
for num in numbers:
print(num)
6. 键错误
错误15: 字典键不存在
错误信息:
KeyError: 'age'
错误代码:
python
person = {"name": "Alice"}
print(person["age"]) # age键不存在
解决方案:
python
person = {"name": "Alice"}
# 方法1: 使用get方法(推荐)
age = person.get("age") # None
age = person.get("age", 0) # 指定默认值0
# 方法2: 检查键是否存在
if "age" in person:
age = person["age"]
else:
age = 0
# 方法3: 使用try-except
try:
age = person["age"]
except KeyError:
age = 0
# 方法4: 使用defaultdict
from collections import defaultdict
person = defaultdict(int)
person["name"] = "Alice"
print(person["age"]) # 0(自动创建)
7. 属性错误
错误16: 对象没有该属性
错误信息:
AttributeError: 'str' object has no attribute 'append'
AttributeError: 'list' object has no attribute 'split'
错误代码:
python
text = "hello"
text.append("world") # 字符串没有append方法
my_list = [1, 2, 3]
my_list.split(",") # 列表没有split方法
解决方案:
python
# 了解数据类型的方法
text = "hello"
text_list = list(text)
text_list.append("world")
# 或使用正确的类型
text = "hello,world"
text_list = text.split(",")
# 查看对象支持的方法
print(dir(text)) # 查看字符串的所有方法
help(text)
常见场景:
python
# 场景1: None没有属性
result = None
result.append(1) # AttributeError
# 解决
result = []
result.append(1)
# 场景2: 方法拼写错误
text = "hello"
text.uppper() # AttributeError: 'str' object has no attribute 'uppper'
text.upper() # 正确
8. 导入错误
错误17: 模块未找到
错误信息:
ModuleNotFoundError: No module named 'requests'
ImportError: No module named 'requests'
错误代码:
python
import requests # 模块未安装
解决方案:
bash
# 安装缺失的模块
pip install requests
# 查看已安装的包
pip list
# 升级pip
python -m pip install --upgrade pip
常见问题:
python
# 问题1: 多个Python版本
# 确认pip对应的Python版本
python --version
pip --version
# 使用python -m pip
python -m pip install requests
# 问题2: 虚拟环境
# 确认是否在虚拟环境中
# 激活虚拟环境后再安装
# 问题3: 自定义模块路径
import sys
sys.path.append('/path/to/module')
import mymodule
错误18: 循环导入
错误信息:
ImportError: cannot import name 'function' from partially initialized module
错误场景:
python
# module_a.py
from module_b import func_b
def func_a():
return func_b()
# module_b.py
from module_a import func_a
def func_b():
return func_a()
解决方案:
python
# 方法1: 在函数内导入
# module_a.py
def func_a():
from module_b import func_b
return func_b()
# 方法2: 重构代码结构
# 将共同依赖的部分提取到第三个模块
# 方法3: 使用importlib
import importlib
module_b = importlib.import_module('module_b')
9. 缩进错误
错误19: 缩进不一致
错误信息:
IndentationError: unexpected indent
IndentationError: unindent does not match any outer indentation level
TabError: inconsistent use of tabs and spaces in indentation
错误代码:
python
def hello():
print("Hello")
print("World") # 缩进不一致
解决方案:
python
def hello():
print("Hello")
print("World") # 统一使用4个空格
最佳实践:
- 统一使用4个空格缩进(不要用Tab)
- 在IDE中设置Tab自动转换为空格
- 使用代码格式化工具(如black、autopep8)
python
# 配置VS Code
# settings.json
{
"editor.tabSize": 4,
"editor.insertSpaces": true,
"python.formatting.provider": "black"
}
10. 除零错误
错误20: 除以零
错误信息:
ZeroDivisionError: division by zero
错误代码:
python
result = 10 / 0
result = 10 % 0
解决方案:
python
# 方法1: 检查除数
divisor = 0
if divisor != 0:
result = 10 / divisor
else:
result = 0 # 或其他默认值
# 方法2: try-except
try:
result = 10 / divisor
except ZeroDivisionError:
result = float('inf') # 或0或None
# 方法3: 使用三元表达式
result = 10 / divisor if divisor != 0 else 0
11. 文件错误
错误21: 文件未找到
错误信息:
FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'
错误代码:
python
with open("data.txt", "r") as f:
content = f.read()
解决方案:
python
import os
# 方法1: 检查文件是否存在
if os.path.exists("data.txt"):
with open("data.txt", "r") as f:
content = f.read()
else:
print("文件不存在")
# 方法2: 使用try-except
try:
with open("data.txt", "r") as f:
content = f.read()
except FileNotFoundError:
print("文件不存在,创建新文件")
with open("data.txt", "w") as f:
f.write("")
# 方法3: 使用绝对路径
import os
file_path = os.path.join(os.getcwd(), "data.txt")
with open(file_path, "r") as f:
content = f.read()
# 方法4: 使用pathlib (推荐)
from pathlib import Path
file = Path("data.txt")
if file.exists():
content = file.read_text()
else:
file.write_text("")
路径问题排查:
python
import os
# 查看当前工作目录
print(os.getcwd())
# 列出当前目录文件
print(os.listdir("."))
# 获取文件绝对路径
print(os.path.abspath("data.txt"))
# Windows路径问题
# 错误
path = "C:\test\file.txt" # \t会被解释为Tab
# 正确
path = r"C:\test\file.txt" # 原始字符串
path = "C:\\test\\file.txt" # 转义
path = "C:/test/file.txt" # 使用正斜杠
12. 权限错误
错误22: 权限被拒绝
错误信息:
PermissionError: [Errno 13] Permission denied: 'file.txt'
解决方案:
python
# 1. 检查文件权限
import os
import stat
file = "file.txt"
if os.access(file, os.W_OK):
with open(file, "w") as f:
f.write("content")
else:
print("没有写权限")
# 2. 修改文件权限(Linux/Mac)
os.chmod(file, stat.S_IWRITE)
# 3. 以管理员身份运行(Windows)
# 4. 检查文件是否被占用
# 确保文件已关闭
with open(file, "r") as f:
content = f.read()
# 文件在with块结束后自动关闭
13. 路径错误
错误23: 操作系统错误
错误信息:
OSError: [Errno 22] Invalid argument
IsADirectoryError: [Errno 21] Is a directory: 'folder_name'
NotADirectoryError: [Errno 20] Not a directory: 'file.txt'
错误代码:
python
# 场景1: 试图打开文件夹
with open("folder_name", "r") as f:
content = f.read()
# 场景2: 路径包含非法字符
with open("file:name.txt", "w") as f: # 冒号在Windows中非法
f.write("content")
# 场景3: 将文件当作目录
os.chdir("file.txt") # file.txt是文件,不是目录
解决方案:
python
import os
from pathlib import Path
# 方法1: 检查路径类型
path = "folder_name"
if os.path.isfile(path):
with open(path, "r") as f:
content = f.read()
elif os.path.isdir(path):
print(f"{path}是目录,不是文件")
# 方法2: 使用pathlib
path = Path("folder_name")
if path.is_file():
content = path.read_text()
elif path.is_dir():
# 列出目录内容
files = list(path.iterdir())
print(files)
# 方法3: 避免非法字符
# Windows非法字符: < > : " / \ | ? *
import re
def sanitize_filename(filename):
"""移除文件名中的非法字符"""
return re.sub(r'[<>:"/\\|?*]', '_', filename)
safe_name = sanitize_filename("file:name.txt") # "file_name.txt"
with open(safe_name, "w") as f:
f.write("content")
14. 递归错误
错误24: 超过最大递归深度
错误信息:
RecursionError: maximum recursion depth exceeded
错误代码:
python
def factorial(n):
return n * factorial(n - 1) # 缺少终止条件
result = factorial(5)
解决方案:
python
# 方法1: 添加终止条件
def factorial(n):
if n == 0 or n == 1:
return 1
return n * factorial(n - 1)
# 方法2: 使用迭代代替递归
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
# 方法3: 增加递归深度限制(谨慎使用)
import sys
sys.setrecursionlimit(3000) # 默认1000
15. 编码错误
错误25: Unicode解码错误
错误信息:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0
错误代码:
python
with open("file.txt", "r") as f:
content = f.read()
解决方案:
python
# 方法1: 指定正确编码
with open("file.txt", "r", encoding="gbk") as f:
content = f.read()
# 方法2: 忽略错误
with open("file.txt", "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
# 方法3: 替换错误字符
with open("file.txt", "r", encoding="utf-8", errors="replace") as f:
content = f.read()
# 方法4: 自动检测编码
import chardet
with open("file.txt", "rb") as f:
raw_data = f.read()
result = chardet.detect(raw_data)
encoding = result['encoding']
with open("file.txt", "r", encoding=encoding) as f:
content = f.read()
16. 内存错误
错误26: 内存不足
错误信息:
MemoryError
错误场景:
python
# 场景1: 创建超大列表
huge_list = [0] * 10**10 # 尝试创建100亿个元素
# 场景2: 无限制读取大文件
with open("huge_file.txt", "r") as f:
content = f.read() # 文件太大,内存不够
# 场景3: 递归创建大量对象
def create_objects():
objects = []
while True:
objects.append([0] * 1000000) # 持续创建大对象
解决方案:
python
# 方法1: 使用生成器代替列表
def number_generator(n):
for i in range(n):
yield i
# 使用生成器,不占用大量内存
gen = number_generator(10**10)
for num in gen:
print(num)
# 方法2: 分块读取大文件
def read_large_file(file_path, chunk_size=1024):
with open(file_path, "r") as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
yield chunk
for chunk in read_large_file("huge_file.txt"):
process(chunk)
# 方法3: 使用迭代器
with open("huge_file.txt", "r") as f:
for line in f: # 逐行读取,而不是一次性读取全部
process(line)
# 方法4: 限制数据结构大小
from collections import deque
# 使用固定大小的deque
recent_items = deque(maxlen=1000)
for item in data_stream:
recent_items.append(item) # 自动移除最旧的元素
17. 溢出错误
错误27: 数值溢出
错误信息:
OverflowError: (34, 'Result too large')
OverflowError: int too large to convert to float
错误代码:
python
import math
# 场景1: 指数运算溢出
result = math.exp(1000) # e^1000太大
# 场景2: 阶乘溢出
result = math.factorial(100000)
float_result = float(result) # 转换为float时溢出
解决方案:
python
import math
from decimal import Decimal
# 方法1: 使用Decimal处理大数
num = Decimal(10) ** 1000
print(num)
# 方法2: 处理溢出异常
try:
result = math.exp(1000)
except OverflowError:
result = float('inf') # 使用无穷大表示
print("结果太大,使用无穷大表示")
# 方法3: 使用对数处理大数计算
# 计算 e^1000,用 log 表示
log_result = 1000 # ln(e^1000) = 1000
print(f"log(result) = {log_result}")
# 方法4: 整数运算(Python 3整数无限精度)
big_num = 2 ** 10000 # Python可以处理任意大的整数
print(f"位数: {len(str(big_num))}")
18. 未绑定局部变量错误
错误28: 局部变量未赋值前引用
错误信息:
UnboundLocalError: local variable 'x' referenced before assignment
错误代码:
python
x = 10
def modify():
print(x) # 错误!
x = 20 # 这行让x变成局部变量,但print时还未赋值
modify()
原因: Python看到函数内有 x = 20,就把x当作局部变量,但在赋值前就引用了它。
解决方案:
python
# 方法1: 使用global关键字
x = 10
def modify():
global x
print(x) # 10
x = 20
print(x) # 20
modify()
print(x) # 20
# 方法2: 使用不同的变量名
x = 10
def modify():
print(x) # 访问全局变量x
local_x = 20 # 局部变量使用不同名字
return local_x
# 方法3: 使用nonlocal(嵌套函数)
def outer():
x = 10
def inner():
nonlocal x
print(x) # 10
x = 20
inner()
print(x) # 20
# 方法4: 返回值而不是修改全局变量
def modify(value):
print(value)
return value + 10
x = 10
x = modify(x)
另一个常见场景:
python
total = 0
def add_to_total(n):
total += n # UnboundLocalError
return total
# 解决方案
def add_to_total(n):
global total
total += n
return total
21. 逻辑错误
错误29: 无限循环
错误场景:
python
# 场景1: 条件永远为真
while True:
print("无限循环")
# 忘记break
# 场景2: 循环变量未更新
i = 0
while i < 10:
print(i)
# 忘记 i += 1
解决方案:
python
# 方法1: 添加退出条件
while True:
user_input = input("输入quit退出:")
if user_input == "quit":
break
print(user_input)
# 方法2: 更新循环变量
i = 0
while i < 10:
print(i)
i += 1
# 方法3: 使用for循环
for i in range(10):
print(i)
错误30: 可变默认参数
错误代码:
python
def add_item(item, list=[]):
list.append(item)
return list
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] 期望[2]
print(add_item(3)) # [1, 2, 3] 期望[3]
解决方案:
python
def add_item(item, list=None):
if list is None:
list = []
list.append(item)
return list
print(add_item(1)) # [1]
print(add_item(2)) # [2]
print(add_item(3)) # [3]
原理: 默认参数在函数定义时只创建一次,所有调用共享同一个对象
错误31: 浅拷贝 vs 深拷贝
错误代码:
python
original = [[1, 2], [3, 4]]
copy = original.copy() # 浅拷贝
copy[0][0] = 99
print(original) # [[99, 2], [3, 4]] 原列表也被修改
解决方案:
python
import copy
original = [[1, 2], [3, 4]]
# 浅拷贝(只复制第一层)
shallow = original.copy()
# 深拷贝(递归复制所有层)
deep = copy.deepcopy(original)
deep[0][0] = 99
print(original) # [[1, 2], [3, 4]] 原列表不变
print(deep) # [[99, 2], [3, 4]]
19. 类和对象错误
错误32: 忘记self参数
错误信息:
TypeError: method() takes 0 positional arguments but 1 was given
错误代码:
python
class Person:
def __init__(name, age): # 错误:缺少self
name = name
age = age
def greet(): # 错误:缺少self
print("Hello")
p = Person("Alice", 25) # TypeError
解决方案:
python
class Person:
def __init__(self, name, age): # 正确:第一个参数是self
self.name = name
self.age = age
def greet(self): # 正确:包含self
print(f"Hello, I'm {self.name}")
p = Person("Alice", 25)
p.greet() # Hello, I'm Alice
记住: 类的所有实例方法第一个参数必须是self
错误33: __init__拼写错误
错误代码:
python
class Person:
def _init_(self, name): # 错误:少一个下划线
self.name = name
def __ini__(self, name): # 错误:拼写错误
self.name = name
p = Person("Alice") # TypeError: Person() takes no arguments
解决方案:
python
class Person:
def __init__(self, name): # 正确:两边各两个下划线
self.name = name
p = Person("Alice") # 正确
特殊方法拼写检查清单:
__init__(不是_init_或__ini__)__str__(不是__string__)__repr__(不是__represent__)__len__(不是__length__)
错误34: 类属性 vs 实例属性混淆
错误代码:
python
class Counter:
count = 0 # 类属性,所有实例共享
def __init__(self):
self.count += 1 # 这会创建实例属性,不会修改类属性
c1 = Counter()
c2 = Counter()
print(Counter.count) # 0,类属性没变
解决方案:
python
# 方案1: 使用类属性记录所有实例的计数
class Counter:
count = 0 # 类属性
def __init__(self):
Counter.count += 1 # 修改类属性
c1 = Counter()
c2 = Counter()
print(Counter.count) # 2
# 方案2: 使用实例属性记录每个实例的计数
class Counter:
def __init__(self):
self.count = 0 # 实例属性
def increment(self):
self.count += 1
c1 = Counter()
c2 = Counter()
c1.increment()
print(c1.count) # 1
print(c2.count) # 0
常见陷阱:
python
class MyClass:
items = [] # 类属性,所有实例共享!
def add_item(self, item):
self.items.append(item) # 修改的是类属性
obj1 = MyClass()
obj2 = MyClass()
obj1.add_item("A")
obj2.add_item("B")
print(obj1.items) # ["A", "B"]
print(obj2.items) # ["A", "B"] - 意外!
# 正确做法
class MyClass:
def __init__(self):
self.items = [] # 实例属性,每个实例独立
def add_item(self, item):
self.items.append(item)
20. 继承相关错误
错误35: super()使用错误
错误代码:
python
class Parent:
def __init__(self, name):
self.name = name
class Child(Parent):
def __init__(self, name, age):
# 错误1: 忘记调用父类__init__
self.age = age
c = Child("Alice", 25)
print(c.name) # AttributeError: 'Child' object has no attribute 'name'
# 错误2: super()参数错误
class Child2(Parent):
def __init__(self, name, age):
super(Child2, self).__init__(name) # Python 2风格,Python 3不需要参数
self.age = age
解决方案:
python
class Parent:
def __init__(self, name):
self.name = name
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # Python 3推荐写法
self.age = age
c = Child("Alice", 25)
print(c.name) # Alice
print(c.age) # 25
22. 作用域和闭包错误
错误36: 闭包变量绑定问题
错误代码:
python
# 期望创建3个函数,分别返回0, 1, 2
functions = []
for i in range(3):
functions.append(lambda: i)
print(functions[0]()) # 期望0,实际2
print(functions[1]()) # 期望1,实际2
print(functions[2]()) # 期望2,实际2
原因: 闭包捕获的是变量引用,不是值。循环结束时i=2,所有lambda都返回2。
解决方案:
python
# 方法1: 使用默认参数
functions = []
for i in range(3):
functions.append(lambda x=i: x)
print(functions[0]()) # 0
print(functions[1]()) # 1
print(functions[2]()) # 2
# 方法2: 使用functools.partial
from functools import partial
def return_value(x):
return x
functions = [partial(return_value, i) for i in range(3)]
# 方法3: 使用函数工厂
def make_function(x):
return lambda: x
functions = [make_function(i) for i in range(3)]
# 方法4: 使用列表推导式(推荐)
functions = [lambda x=i: x for i in range(3)]
23. 比较运算错误
错误37: is vs == 混淆
错误代码:
python
# 场景1: 比较字符串
a = "hello"
b = "hello"
print(a is b) # 可能True也可能False(取决于实现)
# 场景2: 比较数字
x = 1000
y = 1000
print(x is y) # False
# 场景3: 比较None(正确用法)
value = None
if value == None: # 不推荐
print("None")
解决方案:
python
# is: 检查对象身份(内存地址)
# ==: 检查值是否相等
# 比较值用 ==
a = "hello"
b = "hello"
print(a == b) # True
x = 1000
y = 1000
print(x == y) # True
# 只有比较None、True、False才用is
value = None
if value is None: # 正确
print("None")
# 比较True/False
flag = True
if flag is True: # 可以,但直接用if flag更好
print("True")
if flag: # 更Pythonic
print("True")
特殊情况:
python
# 小整数缓存池(-5到256)
a = 10
b = 10
print(a is b) # True(因为在缓存范围内)
a = 1000
b = 1000
print(a is b) # False(超出缓存范围)
# 字符串驻留
a = "hello"
b = "hello"
print(a is b) # 可能True(Python优化)
a = "hello world"
b = "hello world"
print(a is b) # 可能False(包含空格)
错误38: 链式比较误用
错误代码:
python
# 错误理解
x = 5
if x == 3 or 4 or 5: # 错误!总是True
print("x是3、4或5")
# 实际等价于
if x == 3 or 4 or 5: # (x == 3) or 4 or 5
# 4和5都是真值,所以总是True
解决方案:
python
x = 5
# 方法1: 使用in
if x in (3, 4, 5):
print("x是3、4或5")
# 方法2: 多个or
if x == 3 or x == 4 or x == 5:
print("x是3、4或5")
# 链式比较(正确用法)
age = 25
if 18 <= age < 60: # 正确:18 <= age and age < 60
print("工作年龄")
# 错误用法
if 1 < x > 5: # 等价于 1 < x and x > 5
print("这个条件很奇怪") # x必须同时大于1和5
25. 列表操作错误
错误39: 遍历时修改列表
错误代码:
python
# 场景1: 删除元素
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # 错误!会跳过元素
print(numbers) # [1, 3, 5] 或 [1, 3, 4, 5](不确定)
# 场景2: 添加元素
numbers = [1, 2, 3]
for num in numbers:
numbers.append(num * 2) # 无限循环!
解决方案:
python
# 方法1: 使用列表推导式(推荐)
numbers = [1, 2, 3, 4, 5]
numbers = [num for num in numbers if num % 2 != 0]
print(numbers) # [1, 3, 5]
# 方法2: 遍历副本
numbers = [1, 2, 3, 4, 5]
for num in numbers[:]: # 遍历副本
if num % 2 == 0:
numbers.remove(num)
# 方法3: 反向遍历
numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers) - 1, -1, -1):
if numbers[i] % 2 == 0:
del numbers[i]
# 方法4: filter函数
numbers = [1, 2, 3, 4, 5]
numbers = list(filter(lambda x: x % 2 != 0, numbers))
错误40: 列表 * 运算符陷阱
错误代码:
python
# 创建二维列表
matrix = [[0] * 3] * 3
matrix[0][0] = 1
print(matrix) # [[1, 0, 0], [1, 0, 0], [1, 0, 0]] - 意外!
原因: * 3 创建了3个指向同一个列表的引用
解决方案:
python
# 方法1: 列表推导式(推荐)
matrix = [[0] * 3 for _ in range(3)]
matrix[0][0] = 1
print(matrix) # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
# 方法2: 使用循环
matrix = []
for i in range(3):
matrix.append([0] * 3)
# 方法3: 使用numpy(处理数值)
import numpy as np
matrix = np.zeros((3, 3))
26. 字典操作错误
错误41: 遍历时修改字典
错误信息:
RuntimeError: dictionary changed size during iteration
错误代码:
python
data = {"a": 1, "b": 2, "c": 3}
for key in data:
if data[key] == 2:
del data[key] # RuntimeError
解决方案:
python
# 方法1: 遍历副本(推荐)
data = {"a": 1, "b": 2, "c": 3}
for key in list(data.keys()):
if data[key] == 2:
del data[key]
# 方法2: 字典推导式
data = {"a": 1, "b": 2, "c": 3}
data = {k: v for k, v in data.items() if v != 2}
# 方法3: 收集要删除的键
data = {"a": 1, "b": 2, "c": 3}
to_delete = [key for key, value in data.items() if value == 2]
for key in to_delete:
del data[key]
错误42: 字典key必须是可哈希的
错误信息:
TypeError: unhashable type: 'list'
错误代码:
python
# 列表不能作为字典key
data = {[1, 2]: "value"} # TypeError
# 字典不能作为key
data = {{}: "value"} # TypeError
解决方案:
python
# 方法1: 使用元组代替列表
data = {(1, 2): "value"} # 正确
print(data[(1, 2)]) # "value"
# 方法2: 使用frozenset代替set
data = {frozenset([1, 2]): "value"} # 正确
# 方法3: 将列表转换为字符串
data = {str([1, 2]): "value"} # 正确,但不推荐
# 可哈希类型:int, float, str, tuple, frozenset
# 不可哈希类型:list, dict, set
27. 字符串操作错误
错误43: 字符串是不可变的
错误信息:
TypeError: 'str' object does not support item assignment
错误代码:
python
text = "Hello"
text[0] = "h" # TypeError: 字符串不可修改
解决方案:
python
# 方法1: 切片和拼接
text = "Hello"
text = "h" + text[1:] # "hello"
# 方法2: 转换为列表
text = "Hello"
chars = list(text)
chars[0] = "h"
text = "".join(chars) # "hello"
# 方法3: 使用replace
text = "Hello"
text = text.replace("H", "h", 1) # "hello" (只替换1次)
# 方法4: 使用字符串方法
text = "Hello"
text = text.lower() # "hello"
错误44: 字符串编码/解码混淆
错误代码:
python
# 错误1: 对str调用encode多次
text = "你好"
encoded = text.encode("utf-8") # bytes
double_encoded = encoded.encode("utf-8") # AttributeError
# 错误2: 对bytes调用decode多次
data = b"hello"
decoded = data.decode("utf-8") # str
double_decoded = decoded.decode("utf-8") # AttributeError
解决方案:
python
# str -(encode)-> bytes -(decode)-> str
# 编码:str -> bytes
text = "你好"
encoded = text.encode("utf-8") # b'\xe4\xbd\xa0\xe5\xa5\xbd'
print(type(encoded)) # <class 'bytes'>
# 解码:bytes -> str
decoded = encoded.decode("utf-8") # "你好"
print(type(decoded)) # <class 'str'>
# 常见场景
# 1. 网络传输(需要bytes)
import socket
text = "Hello"
sock.send(text.encode("utf-8"))
# 2. 文件读写
with open("file.txt", "w", encoding="utf-8") as f:
f.write("你好") # 自动编码
with open("file.txt", "rb") as f: # 二进制模式
data = f.read() # bytes
text = data.decode("utf-8") # 手动解码
30. 迭代器和生成器错误
错误45: 迭代器只能遍历一次
错误代码:
python
numbers = (x * 2 for x in range(5)) # 生成器表达式
# 第一次遍历
for n in numbers:
print(n) # 0, 2, 4, 6, 8
# 第二次遍历
for n in numbers:
print(n) # 什么都不输出!
原因: 生成器和迭代器是一次性的,遍历后就耗尽了。
解决方案:
python
# 方法1: 使用列表(如果数据量不大)
numbers = [x * 2 for x in range(5)] # 列表推导式
for n in numbers:
print(n) # 0, 2, 4, 6, 8
for n in numbers:
print(n) # 0, 2, 4, 6, 8(可以重复遍历)
# 方法2: 重新创建生成器
def get_numbers():
return (x * 2 for x in range(5))
numbers = get_numbers()
for n in numbers:
print(n)
numbers = get_numbers() # 重新创建
for n in numbers:
print(n)
# 方法3: 使用itertools.tee(创建独立迭代器)
import itertools
numbers = (x * 2 for x in range(5))
iter1, iter2 = itertools.tee(numbers, 2)
for n in iter1:
print(n)
for n in iter2:
print(n)
错误46: StopIteration异常
错误代码:
python
numbers = iter([1, 2, 3])
print(next(numbers)) # 1
print(next(numbers)) # 2
print(next(numbers)) # 3
print(next(numbers)) # StopIteration
解决方案:
python
# 方法1: 使用for循环(自动处理)
numbers = iter([1, 2, 3])
for n in numbers:
print(n) # 自动在StopIteration时停止
# 方法2: 使用next的默认值
numbers = iter([1, 2, 3])
while True:
n = next(numbers, None)
if n is None:
break
print(n)
# 方法3: 捕获异常
numbers = iter([1, 2, 3])
try:
while True:
print(next(numbers))
except StopIteration:
pass
31. 装饰器错误
错误47: 装饰器忘记返回函数
错误代码:
python
def my_decorator(func):
def wrapper():
print("Before")
func()
print("After")
# 忘记return wrapper
@my_decorator
def say_hello():
print("Hello")
say_hello() # TypeError: 'NoneType' object is not callable
解决方案:
python
def my_decorator(func):
def wrapper(*args, **kwargs):
print("Before")
result = func(*args, **kwargs)
print("After")
return result
return wrapper # 必须返回wrapper
@my_decorator
def say_hello():
print("Hello")
say_hello()
# Before
# Hello
# After
错误48: 装饰器丢失函数元数据
错误代码:
python
def my_decorator(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@my_decorator
def say_hello():
"""问候函数"""
print("Hello")
print(say_hello.__name__) # "wrapper" 而不是 "say_hello"
print(say_hello.__doc__) # None
解决方案:
python
from functools import wraps
def my_decorator(func):
@wraps(func) # 保留原函数的元数据
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@my_decorator
def say_hello():
"""问候函数"""
print("Hello")
print(say_hello.__name__) # "say_hello"
print(say_hello.__doc__) # "问候函数"
32. 异常处理错误
错误49: 裸except捕获所有异常
错误代码:
python
try:
result = 10 / 0
except: # 捕获所有异常,包括KeyboardInterrupt
print("发生错误")
问题:
- 捕获SystemExit,导致程序无法正常退出
- 捕获KeyboardInterrupt,无法用Ctrl+C中断程序
- 难以调试
解决方案:
python
# 方法1: 捕获特定异常(推荐)
try:
result = 10 / 0
except ZeroDivisionError:
print("除数不能为0")
except ValueError:
print("值错误")
# 方法2: 捕获Exception(不包括系统异常)
try:
result = 10 / 0
except Exception as e:
print(f"发生错误: {e}")
# 方法3: 多个异常
try:
result = int("abc")
except (ValueError, TypeError) as e:
print(f"转换错误: {e}")
错误50: 异常被吞没
错误代码:
python
try:
# 大量代码
process_data()
calculate()
save_result()
except:
pass # 错误被吞没,无法调试
解决方案:
python
# 方法1: 记录日志
import logging
try:
process_data()
except Exception as e:
logging.error(f"处理失败: {e}", exc_info=True)
raise # 重新抛出异常
# 方法2: 至少打印错误
try:
process_data()
except Exception as e:
print(f"错误: {e}")
import traceback
traceback.print_exc()
raise
# 方法3: 只捕获预期的异常
try:
process_data()
except ValueError: # 只捕获特定异常
handle_value_error()
# 其他异常会正常传播
33. 上下文管理器错误
错误51: 忘记关闭文件
错误代码:
python
f = open("file.txt", "w")
f.write("content")
# 忘记f.close()
# 可能导致数据丢失或文件被锁定
解决方案:
python
# 方法1: 使用with语句(推荐)
with open("file.txt", "w") as f:
f.write("content")
# 自动关闭文件
# 方法2: try-finally
f = open("file.txt", "w")
try:
f.write("content")
finally:
f.close() # 确保关闭
# 方法3: 多个文件
with open("input.txt", "r") as f_in, \
open("output.txt", "w") as f_out:
content = f_in.read()
f_out.write(content.upper())
错误52: 自定义上下文管理器错误
错误代码:
python
class MyContext:
def __enter__(self):
print("Enter")
# 忘记return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exit")
with MyContext() as ctx:
print(ctx) # None
解决方案:
python
class MyContext:
def __enter__(self):
print("Enter")
return self # 必须返回
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exit")
if exc_type is not None:
print(f"异常: {exc_val}")
return False # False表示不抑制异常
with MyContext() as ctx:
print(ctx) # <__main__.MyContext object>
# 使用contextlib简化
from contextlib import contextmanager
@contextmanager
def my_context():
print("Enter")
try:
yield "value"
finally:
print("Exit")
with my_context() as value:
print(value) # "value"
45. 性能问题
问题53: 列表拼接效率低
低效代码:
python
result = ""
for i in range(10000):
result += str(i) # 每次都创建新字符串
优化方案:
python
# 使用join
result = "".join(str(i) for i in range(10000))
# 或使用列表
parts = []
for i in range(10000):
parts.append(str(i))
result = "".join(parts)
问题54: 重复计算
低效代码:
python
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(35)) # 很慢
优化方案:
python
# 使用缓存
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
print(fibonacci(35)) # 很快
问题55: 使用+而不是join拼接字符串
低效代码:
python
# 在循环中用+拼接
words = ["hello", "world", "python"] * 1000
result = ""
for word in words:
result += word # 每次创建新字符串,O(n²)
优化方案:
python
# 使用join,O(n)
words = ["hello", "world", "python"] * 1000
result = "".join(words)
# 或者使用分隔符
result = " ".join(words)
问题56: 不使用列表推导式
低效代码:
python
# 传统方式
squares = []
for i in range(1000):
squares.append(i ** 2)
优化方案:
python
# 列表推导式(更快更简洁)
squares = [i ** 2 for i in range(1000)]
# 如果不需要整个列表,使用生成器
squares = (i ** 2 for i in range(1000))
问题57: 多次计算len()
低效代码:
python
my_list = list(range(1000))
for i in range(len(my_list)):
if i < len(my_list) - 1: # 每次都计算len
process(my_list[i])
优化方案:
python
my_list = list(range(1000))
length = len(my_list) # 只计算一次
for i in range(length):
if i < length - 1:
process(my_list[i])
# 或者使用enumerate
for i, item in enumerate(my_list):
if i < len(my_list) - 1:
process(item)
问题58: 检查元素是否在列表中(O(n))
低效代码:
python
items = list(range(10000))
# 检查元素,O(n)
if 5000 in items:
print("找到了")
优化方案:
python
# 使用集合,O(1)
items = set(range(10000))
if 5000 in items:
print("找到了")
# 如果需要同时保持顺序和快速查找
items_list = list(range(10000))
items_set = set(items_list)
if 5000 in items_set: # 快速查找
print("找到了")
24. 布尔运算错误
错误55: not优先级问题
错误代码:
python
x = 5
# 错误理解
if not x == 10: # 被解析为 not (x == 10)
print("x不是10")
# 想要表达的可能是
if x != 10:
print("x不是10")
正确理解:
python
# not的优先级低于比较运算符
x = 5
print(not x == 10) # True,等价于 not (x == 10)
# 如果想要其他效果,使用括号
print((not x) == 10) # False,先计算not x
# 更清晰的写法
if x != 10: # 推荐
print("x不是10")
错误56: and/or返回值误解
错误代码:
python
# 误以为and/or总是返回True/False
x = 10
y = 20
result = x and y
print(result) # 20,不是True!
result = x or y
print(result) # 10,不是True!
正确理解:
python
# and返回第一个假值,或最后一个真值
print(0 and 10) # 0
print(10 and 20) # 20
print(None and 10) # None
# or返回第一个真值,或最后一个假值
print(0 or 10) # 10
print(10 or 20) # 10
print(0 or None) # None
# 实用场景:提供默认值
name = input("姓名: ") or "匿名" # 如果输入为空,使用"匿名"
# 短路求值
def expensive_operation():
print("执行中...")
return True
# 如果第一个条件为假,不会执行第二个
if False and expensive_operation(): # 不会打印"执行中..."
pass
41. import错误
错误57: 相对导入错误
错误信息:
ImportError: attempted relative import with no known parent package
ValueError: attempted relative import beyond top-level package
错误场景:
python
# 项目结构:
# myproject/
# __init__.py
# module_a.py
# module_b.py
# subpackage/
# __init__.py
# module_c.py
# 在module_c.py中
from .. import module_a # 相对导入
# 直接运行会报错
# python module_c.py # ImportError
解决方案:
python
# 方法1: 使用绝对导入(推荐)
from myproject import module_a
# 方法2: 作为模块运行
# python -m myproject.subpackage.module_c
# 方法3: 修改sys.path(不推荐)
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from module_a import something
# 方法4: 使用包管理
# 在项目根目录创建setup.py,安装包
# pip install -e .
错误58: from module import *的陷阱
错误代码:
python
# module_a.py
def process():
return "A"
# module_b.py
def process():
return "B"
# main.py
from module_a import *
from module_b import *
print(process()) # "B",module_a的process被覆盖了
解决方案:
python
# 方法1: 导入模块(推荐)
import module_a
import module_b
print(module_a.process()) # "A"
print(module_b.process()) # "B"
# 方法2: 使用as重命名
from module_a import process as process_a
from module_b import process as process_b
print(process_a()) # "A"
print(process_b()) # "B"
# 方法3: 只导入需要的
from module_a import specific_function
from module_b import another_function
42. 数值计算错误
错误59: 浮点数精度问题
错误代码:
python
# 浮点数不精确
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
解决方案:
python
# 方法1: 使用round
result = round(0.1 + 0.2, 2)
print(result) # 0.3
# 方法2: 使用isclose比较
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
# 方法3: 使用Decimal(精确计算)
from decimal import Decimal
result = Decimal('0.1') + Decimal('0.2')
print(result) # 0.3
print(result == Decimal('0.3')) # True
# 方法4: 容差比较
def approx_equal(a, b, tolerance=1e-9):
return abs(a - b) < tolerance
print(approx_equal(0.1 + 0.2, 0.3)) # True
错误60: 整数除法vs浮点除法
错误代码 (Python 2风格):
python
# Python 2中,整数除法返回整数
# print 5 / 2 # 2 (在Python 2中)
# Python 3中,/总是返回浮点数
print(5 / 2) # 2.5
Python 3中的除法:
python
# /: 浮点除法
print(5 / 2) # 2.5
print(4 / 2) # 2.0 (仍是浮点数)
# //: 整数除法(向下取整)
print(5 // 2) # 2
print(-5 // 2) # -3 (向下取整,不是向零取整)
# %: 取余
print(5 % 2) # 1
print(-5 % 2) # 1
# divmod: 同时得到商和余数
quotient, remainder = divmod(5, 2)
print(quotient, remainder) # 2 1
43. 日期时间错误
错误61: 时区问题
错误代码:
python
from datetime import datetime
# 创建不带时区的datetime (naive)
now = datetime.now()
print(now.tzinfo) # None
# 与带时区的datetime比较会出错
import pytz
utc_now = datetime.now(pytz.UTC)
# now < utc_now # TypeError: can't compare offset-naive and offset-aware datetimes
解决方案:
python
from datetime import datetime, timezone
import pytz
# 方法1: 统一使用UTC
utc_now = datetime.now(timezone.utc)
print(utc_now.tzinfo) # UTC
# 方法2: 使用pytz
beijing = pytz.timezone('Asia/Shanghai')
beijing_now = datetime.now(beijing)
# 方法3: 转换时区
utc_time = datetime.now(timezone.utc)
beijing_time = utc_time.astimezone(pytz.timezone('Asia/Shanghai'))
# 方法4: 给naive datetime添加时区
naive = datetime.now()
aware = naive.replace(tzinfo=timezone.utc)
# 推荐:始终使用aware datetime
from datetime import datetime, timezone
def get_current_time():
return datetime.now(timezone.utc)
44. 正则表达式错误
错误62: 特殊字符未转义
错误代码:
python
import re
# 想匹配 "file.txt"
pattern = "file.txt"
text = "my file.txt here"
result = re.search(pattern, text) # 匹配到了,但原因错误
# . 在正则中匹配任意字符
text2 = "my filextxt here"
result2 = re.search(pattern, text2) # 也匹配到了!
解决方案:
python
import re
# 方法1: 转义特殊字符
pattern = r"file\.txt"
text = "my file.txt here"
result = re.search(pattern, text) # 正确匹配
text2 = "my filextxt here"
result2 = re.search(pattern, text2) # None
# 方法2: 使用re.escape
filename = "file.txt"
pattern = re.escape(filename) # 自动转义特殊字符
result = re.search(pattern, text)
# 需要转义的特殊字符: . ^ $ * + ? { } [ ] \ | ( )
special_chars = r". ^ $ * + ? { } [ ] \ | ( )"
错误63: 贪婪vs非贪婪匹配
错误代码:
python
import re
html = "<div>content1</div><div>content2</div>"
# 贪婪匹配(默认)
result = re.findall(r"<div>.*</div>", html)
print(result) # ['<div>content1</div><div>content2</div>']
# 匹配了整个字符串!
解决方案:
python
import re
html = "<div>content1</div><div>content2</div>"
# 方法1: 非贪婪匹配(在量词后加?)
result = re.findall(r"<div>.*?</div>", html)
print(result) # ['<div>content1</div>', '<div>content2</div>']
# 方法2: 使用否定字符类
result = re.findall(r"<div>[^<]*</div>", html)
print(result) # ['<div>content1</div>', '<div>content2</div>']
# 贪婪量词: * + ? {m,n}
# 非贪婪量词: *? +? ?? {m,n}?
34. JSON操作错误
错误64: JSON解析失败
错误信息:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 2 column 5 (char 6)
错误代码:
python
import json
# 场景1: 空字符串
data = ""
result = json.loads(data) # JSONDecodeError
# 场景2: 单引号(JSON要求双引号)
json_str = "{'name': 'Alice'}"
result = json.loads(json_str) # JSONDecodeError
# 场景3: 尾部逗号
json_str = '{"name": "Alice",}'
result = json.loads(json_str) # JSONDecodeError
# 场景4: None vs null
json_str = '{"value": None}'
result = json.loads(json_str) # JSONDecodeError
解决方案:
python
import json
# 方法1: 验证JSON格式
json_str = '{"name": "Alice", "age": 25}'
try:
data = json.loads(json_str)
except json.JSONDecodeError as e:
print(f"JSON解析失败: {e}")
print(f"错误位置: 行{e.lineno}, 列{e.colno}")
data = {}
# 方法2: 处理空字符串
json_str = ""
data = json.loads(json_str) if json_str else {}
# 方法3: Python对象转JSON
data = {"name": "Alice", "value": None}
json_str = json.dumps(data) # '{"name": "Alice", "value": null}'
# 方法4: 读取JSON文件
try:
with open("data.json", "r", encoding="utf-8") as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(f"文件格式错误: {e}")
except FileNotFoundError:
print("文件不存在")
data = {}
# JSON vs Python类型对照
# JSON Python
# object dict
# array list
# string str
# number int/float
# true True
# false False
# null None
35. None类型错误
错误65: NoneType对象操作
错误信息:
AttributeError: 'NoneType' object has no attribute 'method'
TypeError: 'NoneType' object is not subscriptable
TypeError: 'NoneType' object is not iterable
错误代码:
python
# 场景1: 函数忘记return
def get_data():
data = [1, 2, 3]
# 忘记return
result = get_data()
print(result[0]) # TypeError: 'NoneType' object is not subscriptable
# 场景2: 修改列表的方法返回None
numbers = [3, 1, 2]
sorted_numbers = numbers.sort() # sort()返回None
print(sorted_numbers[0]) # TypeError
# 场景3: None调用方法
user = None
print(user.name) # AttributeError
# 场景4: 字典get返回None
data = {"name": "Alice"}
age = data.get("age")
print(age + 10) # TypeError: unsupported operand type(s)
解决方案:
python
# 方法1: 检查None
def get_data():
data = [1, 2, 3]
return data # 记得return
result = get_data()
if result is not None:
print(result[0])
# 方法2: 使用返回新对象的方法
numbers = [3, 1, 2]
sorted_numbers = sorted(numbers) # sorted()返回新列表
print(sorted_numbers[0]) # 1
# 或者
numbers = [3, 1, 2]
numbers.sort() # sort()修改原列表
print(numbers[0]) # 1
# 方法3: 使用默认值
user = None
name = user.name if user is not None else "Unknown"
# 或使用getattr
name = getattr(user, 'name', 'Unknown')
# 方法4: 字典get使用默认值
data = {"name": "Alice"}
age = data.get("age", 0) # 提供默认值0
print(age + 10) # 10
# 方法5: 链式调用保护
class User:
def __init__(self, name):
self.name = name
self.profile = None
user = User("Alice")
# 错误
# city = user.profile.city # AttributeError
# 正确
city = user.profile.city if user.profile else None
# Python 3.8+: 海象运算符
if (profile := user.profile) is not None:
city = profile.city
29. 切片操作错误
错误66: 切片索引错误
常见错误:
python
# 场景1: 反转字符串/列表误用
text = "hello"
reversed_text = text[-1] # 只得到最后一个字符'o',而非反转
# 场景2: 步长为0
numbers = [1, 2, 3, 4, 5]
result = numbers[::0] # ValueError: slice step cannot be zero
# 场景3: 切片赋值长度不匹配理解错误
numbers = [1, 2, 3, 4, 5]
numbers[1:3] = [10] # 可以!切片赋值可以改变长度
# 场景4: 字符串切片赋值
text = "hello"
text[0:2] = "He" # TypeError: 'str' object does not support item assignment
正确用法:
python
# 反转序列
text = "hello"
reversed_text = text[::-1] # "olleh"
numbers = [1, 2, 3, 4, 5]
reversed_numbers = numbers[::-1] # [5, 4, 3, 2, 1]
# 切片步长
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
evens = numbers[::2] # [0, 2, 4, 6, 8] 每隔一个
odds = numbers[1::2] # [1, 3, 5, 7, 9]
reverse = numbers[::-1] # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
# 切片赋值
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [10, 20] # [1, 10, 20, 5] 可以改变长度
numbers[1:1] = [100] # [1, 100, 10, 20, 5] 插入
numbers[1:3] = [] # [1, 20, 5] 删除
# 字符串是不可变的,不能切片赋值
text = "hello"
text = text[:2] + "LL" + text[4:] # "heLLo" 创建新字符串
# 切片技巧
# 复制列表
original = [1, 2, 3]
copy1 = original[:]
copy2 = original.copy()
copy3 = list(original)
# 清空列表
numbers = [1, 2, 3, 4, 5]
numbers[:] = [] # 清空原列表(保持引用)
# vs
numbers = [] # 创建新列表(改变引用)
# 安全的越界切片
numbers = [1, 2, 3]
print(numbers[10:20]) # [] 不会报错
print(numbers[-100:2]) # [1, 2] 负索引会被限制
28. 集合操作错误
错误67: 集合元素必须可哈希
错误信息:
TypeError: unhashable type: 'list'
TypeError: unhashable type: 'dict'
错误代码:
python
# 场景1: 集合中添加列表
my_set = {1, 2, [3, 4]} # TypeError
# 场景2: 集合中添加字典
my_set = {1, 2, {"key": "value"}} # TypeError
# 场景3: 集合推导式
lists = [[1, 2], [3, 4], [1, 2]]
unique = {x for x in lists} # TypeError
解决方案:
python
# 方法1: 使用元组代替列表
my_set = {1, 2, (3, 4)} # 正确
# 方法2: 使用frozenset
set1 = frozenset([1, 2, 3])
set2 = frozenset([4, 5, 6])
my_set = {set1, set2} # 正确
# 方法3: 去重嵌套列表(转换为元组)
lists = [[1, 2], [3, 4], [1, 2]]
unique = {tuple(x) for x in lists}
print(unique) # {(1, 2), (3, 4)}
# 转回列表
unique_lists = [list(x) for x in unique]
# 集合操作
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
union = set1 | set2 # {1, 2, 3, 4, 5, 6} 并集
intersection = set1 & set2 # {3, 4} 交集
difference = set1 - set2 # {1, 2} 差集
symmetric_diff = set1 ^ set2 # {1, 2, 5, 6} 对称差
# 集合去重保持顺序(Python 3.7+字典有序)
items = [1, 2, 3, 2, 1, 4]
unique = list(dict.fromkeys(items)) # [1, 2, 3, 4]
26. 字典操作高级错误(续)
错误68: 字典合并错误
错误代码:
python
# Python 3.9之前的方法
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
# 错误:直接相加
# result = dict1 + dict2 # TypeError
# 低效方法
result = dict1.copy()
for k, v in dict2.items():
result[k] = v
正确方案:
python
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
# Python 3.9+: 使用|运算符
result = dict1 | dict2 # {"a": 1, "b": 3, "c": 4}
# Python 3.5+: 使用**解包
result = {**dict1, **dict2} # {"a": 1, "b": 3, "c": 4}
# 所有版本: 使用update
result = dict1.copy()
result.update(dict2) # {"a": 1, "b": 3, "c": 4}
# 多个字典合并
dict3 = {"d": 5}
result = {**dict1, **dict2, **dict3}
# ChainMap(不复制,创建视图)
from collections import ChainMap
result = ChainMap(dict1, dict2)
print(result["b"]) # 3(优先使用第一个字典)
# 嵌套字典合并
def merge_nested(dict1, dict2):
"""深度合并字典"""
result = dict1.copy()
for key, value in dict2.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = merge_nested(result[key], value)
else:
result[key] = value
return result
d1 = {"a": {"x": 1, "y": 2}, "b": 3}
d2 = {"a": {"y": 3, "z": 4}, "c": 5}
result = merge_nested(d1, d2)
# {"a": {"x": 1, "y": 3, "z": 4}, "b": 3, "c": 5}
36. 三元运算符错误
错误69: 三元运算符语法错误
错误代码:
python
# 错误1: 使用C语言语法
x = 5
# result = x > 10 ? "big" : "small" # SyntaxError
# 错误2: 顺序错误
result = x > 10 : "big" if "small" # SyntaxError
# 错误3: 缺少else
# result = "big" if x > 10 # SyntaxError
正确用法:
python
x = 5
# Python三元运算符: value_if_true if condition else value_if_false
result = "big" if x > 10 else "small" # "small"
# 嵌套三元运算符(不推荐,可读性差)
score = 85
grade = "A" if score >= 90 else "B" if score >= 80 else "C" if score >= 70 else "D"
# 更好的写法:使用if-elif-else
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "D"
# 实用场景
# 1. 设置默认值
name = user_input if user_input else "Anonymous"
# 2. 选择函数
operation = add if mode == "sum" else subtract
result = operation(a, b)
# 3. 列表推导式中使用
numbers = [1, 2, 3, 4, 5]
result = ["even" if n % 2 == 0 else "odd" for n in numbers]
# ["odd", "even", "odd", "even", "odd"]
# 4. 多个条件
x, y = 5, 10
result = "both positive" if x > 0 and y > 0 else "not both positive"
37. f-string格式化错误
错误70: f-string使用错误
错误信息:
SyntaxError: f-string: expecting '}'
SyntaxError: f-string expression part cannot include a backslash
ValueError: Unknown format code 'x' for object of type 'str'
错误代码:
python
# 错误1: 花括号不匹配
name = "Alice"
# text = f"Hello {name" # SyntaxError
# 错误2: f-string中使用反斜杠
# text = f"path: {os.path.join('a', 'b')}" # 某些情况下报错
# text = f"newline: {\n}" # SyntaxError
# 错误3: 引号嵌套错误
# text = f"{'it's'}" # SyntaxError
# 错误4: 格式说明符错误
value = "text"
# formatted = f"{value:d}" # ValueError: 'd'只能用于数字
正确用法:
python
# 基础用法
name = "Alice"
age = 25
text = f"Name: {name}, Age: {age}"
# 表达式
a, b = 5, 3
result = f"{a} + {b} = {a + b}" # "5 + 3 = 8"
# 格式说明符
# 数字格式化
number = 1234.5678
f"{number:.2f}" # "1234.57" 保留2位小数
f"{number:,.2f}" # "1,234.57" 千分位分隔符
f"{number:>10.2f}" # " 1234.57" 右对齐,宽度10
f"{number:<10.2f}" # "1234.57 " 左对齐
f"{number:^10.2f}" # " 1234.57 " 居中对齐
# 整数格式化
num = 42
f"{num:05d}" # "00042" 填充0,宽度5
f"{num:b}" # "101010" 二进制
f"{num:x}" # "2a" 十六进制
f"{num:o}" # "52" 八进制
# 百分比
ratio = 0.8567
f"{ratio:.2%}" # "85.67%"
# 科学记数法
large = 1234567890
f"{large:e}" # "1.234568e+09"
# 日期时间
from datetime import datetime
now = datetime.now()
f"{now:%Y-%m-%d %H:%M:%S}" # "2024-01-04 10:30:45"
# 处理特殊字符
# 方法1: 使用不同的引号
text = f"{'it\'s'}" # 转义内部引号
text = f'''{"it's"}''' # 使用三引号
# 方法2: 反斜杠问题
import os
path = os.path.join('a', 'b')
text = f"path: {path}" # 先计算,再放入f-string
# 换行符
nl = "\n"
text = f"line1{nl}line2"
# 调试用f-string(Python 3.8+)
x = 10
print(f"{x=}") # "x=10"
print(f"{x*2=}") # "x*2=20"
# 宽度和精度
value = 123.456
f"{value:10.2f}" # " 123.46" 总宽度10,小数点后2位
# 对齐填充
text = "hello"
f"{text:*^10}" # "**hello***" 用*填充,居中,宽度10
f"{text:->10}" # "-----hello" 用-填充,右对齐
f"{text:-<10}" # "hello-----" 用-填充,左对齐
38. 环境和路径错误
错误71: 环境变量错误
错误代码:
python
import os
# 场景1: 环境变量不存在
api_key = os.environ["API_KEY"] # KeyError
# 场景2: 路径分隔符问题
# Windows vs Linux
path = "C:\new\test" # \n和\t会被转义
解决方案:
python
import os
from pathlib import Path
# 方法1: 使用get方法
api_key = os.environ.get("API_KEY") # None if not exists
api_key = os.environ.get("API_KEY", "default_key") # 提供默认值
# 方法2: 使用getenv
api_key = os.getenv("API_KEY", "default_key")
# 方法3: 检查是否存在
if "API_KEY" in os.environ:
api_key = os.environ["API_KEY"]
else:
raise ValueError("API_KEY环境变量未设置")
# 设置环境变量
os.environ["MY_VAR"] = "value"
# 跨平台路径处理
# 方法1: 使用pathlib(推荐)
base = Path("C:/Users/data")
file = base / "file.txt" # 自动处理分隔符
# 方法2: os.path.join
path = os.path.join("folder", "subfolder", "file.txt")
# 方法3: 原始字符串
path = r"C:\new\test" # Windows
path = "C:/new/test" # 也可以使用正斜杠
# 方法4: 使用os.sep
path = f"folder{os.sep}file.txt" # 自动使用正确的分隔符
# .env文件管理(需要python-dotenv)
# pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # 加载.env文件
api_key = os.getenv("API_KEY")
# 获取脚本所在目录
script_dir = Path(__file__).parent
config_file = script_dir / "config.json"
# 获取用户目录
home = Path.home() # /home/username 或 C:\Users\username
39. 列表推导式高级错误
错误72: 列表推导式常见陷阱
错误代码:
python
# 陷阱1: 变量泄露(Python 2问题,Python 3已修复)
# Python 2中,循环变量会泄露
# [i for i in range(10)]
# print(i) # 9(Python 2), NameError(Python 3)
# 陷阱2: 在推导式中修改原列表
numbers = [1, 2, 3, 4, 5]
# 危险!可能导致不可预测的行为
result = [numbers.pop() if x > 2 else x for x in numbers]
# 陷阱3: 推导式过于复杂
# 可读性差
result = [x*y for x in range(10) if x % 2 == 0
for y in range(10) if y % 3 == 0 if x*y > 10]
# 陷阱4: 推导式中的闭包
functions = [lambda: i for i in range(5)]
print([f() for f in functions]) # [4, 4, 4, 4, 4] 都是4!
正确用法:
python
# 基础列表推导式
squares = [x**2 for x in range(10)]
# 带条件
evens = [x for x in range(10) if x % 2 == 0]
# if-else在推导式中
result = [x if x > 0 else 0 for x in [-2, -1, 0, 1, 2]]
# [0, 0, 0, 1, 2]
# 嵌套循环
matrix = [[i*j for j in range(3)] for i in range(3)]
# [[0, 0, 0], [0, 1, 2], [0, 2, 4]]
# 展平嵌套列表
nested = [[1, 2], [3, 4], [5, 6]]
flat = [item for sublist in nested for item in sublist]
# [1, 2, 3, 4, 5, 6]
# 字典推导式
squares_dict = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 集合推导式
unique_lengths = {len(word) for word in ["hello", "world", "hi"]}
# {2, 5}
# 复杂逻辑用普通循环
# 不好
result = [x*y for x in range(10) if x % 2 == 0
for y in range(10) if y % 3 == 0 if x*y > 10]
# 更好
result = []
for x in range(10):
if x % 2 == 0:
for y in range(10):
if y % 3 == 0 and x * y > 10:
result.append(x * y)
# 闭包问题解决
functions = [lambda i=i: i for i in range(5)]
print([f() for f in functions]) # [0, 1, 2, 3, 4]
# 生成器表达式(节省内存)
# 列表推导式
big_list = [x**2 for x in range(1000000)] # 占用大量内存
# 生成器表达式
big_gen = (x**2 for x in range(1000000)) # 几乎不占内存
for value in big_gen:
process(value)
40. 类型转换错误
错误73: 隐式类型转换误解
错误代码:
python
# Python不会自动类型转换
# 场景1: 布尔值转换
value = "False"
if value: # True!非空字符串是真值
print("This prints")
# 场景2: 列表/字典转布尔
empty_list = []
if not empty_list: # True,空列表是假值
print("List is empty")
# 场景3: 数字字符串比较
print("10" > "9") # False!字符串按字典序比较
print("10" > "2") # False!
# 场景4: int和float混合
result = 10 / 3 # 3.333... float
print(type(result)) # <class 'float'>
正确理解:
python
# 显式类型转换
# 字符串转布尔
value = "False"
bool_value = value.lower() == "true" # False
# 或使用distutils(不推荐,已弃用)
import json
bool_value = json.loads(value.lower()) # False
# 真值测试
# 假值: False, None, 0, 0.0, '', [], {}, set()
# 其他都是真值
# 空容器检查
my_list = []
if len(my_list) == 0: # 明确
pass
if not my_list: # Pythonic
pass
# 数字字符串比较
print(int("10") > int("9")) # True
# 自然排序
numbers = ["1", "10", "2", "20"]
sorted(numbers) # ['1', '10', '2', '20'] 字典序
sorted(numbers, key=int) # ['1', '2', '10', '20'] 数值序
# 类型检查
value = "123"
if isinstance(value, str):
number = int(value)
# 安全的类型转换
def safe_int(value, default=0):
"""安全转换为整数"""
try:
return int(value)
except (ValueError, TypeError):
return default
# 多个值转换
values = ["1", "2", "abc", "4"]
numbers = [safe_int(v) for v in values] # [1, 2, 0, 4]
# 类型注解(Python 3.5+)
def add(a: int, b: int) -> int:
return a + b
# 注意:类型注解不强制类型,只是提示
add("1", "2") # "12",不会报错!需要使用mypy等工具检查
附录A:调试技巧
技巧1: 使用print调试
python
def calculate(a, b):
print(f"调试: a={a}, b={b}") # 调试输出
result = a * b
print(f"调试: result={result}")
return result
技巧2: 使用assert
python
def divide(a, b):
assert b != 0, "除数不能为0"
return a / b
技巧3: 使用logging
python
import logging
logging.basicConfig(level=logging.DEBUG)
def process_data(data):
logging.debug(f"处理数据: {data}")
logging.info("数据处理成功")
return data
技巧4: 使用pdb调试器
python
import pdb
def buggy_function(x):
pdb.set_trace() # 设置断点
result = x * 2
return result
技巧5: 使用IDE断点调试
- VS Code: F9设置断点,F5开始调试
- PyCharm: 左键点击行号设置断点
附录B:错误信息速查表
基础错误(按频率: 最常见)
| 错误类型 | 常见原因 |
|---------|---------|---------|
| SyntaxError | 缺少冒号/括号/引号不匹配 |
| NameError | 变量未定义、拼写错误 | 定义变量、检查拼写 |
| TypeError | 类型不匹配、参数错误 |
| IndentationError | 缩进不一致、Tab/空格混用 | 统一使用4空格 |
| AttributeError | 属性/方法不存在、None调用 |
| ValueError | 值错误、转换失败、解包错误 | 验证输入、try-except |
| IndexError | 列表索引越界 |
| KeyError | 字典键不存在 | 使用get()、检查键 |
| ImportError | 模块未安装/未找到、循环导入 |
| ZeroDivisionError | 除以零 | 检查除数!=0 |
| FileNotFoundError | 文件路径错误、文件不存在 |
运行时错误
| 错误类型 | 常见原因 | 快速解决 |
|---------|---------|
| UnboundLocalError | 局部变量赋值前引用 | 使用global/nonlocal |
| RecursionError | 递归深度超限、缺终止条件 |
| UnicodeDecodeError | 编码不匹配 | 指定encoding参数 |
| PermissionError | 文件权限不足 |
| OSError | 路径错误、文件操作失败 | 检查路径类型、权限 |
| MemoryError | 内存不足 |
| OverflowError | 数值溢出 | 使用Decimal、检查范围 |
| StopIteration | 迭代器耗尽 |
| RuntimeError | 字典迭代时修改 | 遍历副本list(dict.keys()) |
面向对象错误
| 错误 | 原因 |
|---------|---------|---------|
| 忘记self | 方法定义缺少self参数 |
| __init__拼写错误 | 下划线数量错误 | 两边各2个下划线 |
| 类属性混淆 | 类属性vs实例属性 |
| super()错误 | 忘记调用父类__init__ | super().init() |
逻辑错误
| 错误 | 原因 | 解决 |
|---|---|---|
| 无限循环 | 缺少退出条件 | 添加break、更新变量 |
| 可变默认参数 | 默认参数是列表/字典 | 使用None,在函数内创建 |
| 浅拷贝问题 | copy()只复制第一层 | 使用copy.deepcopy() |
| 闭包变量绑定 | lambda捕获变量引用 | 使用默认参数x=i |
| is vs == | 比较对象身份而非值 | 比较值用==,None用is |
| 链式比较误用 | x==3 or 4总是True | 使用x in (3,4) |
数据结构操作错误
| 错误 | 原因 | 解决 |
|---|---|---|
| 遍历时修改列表 | 删除元素导致索引错位 | 遍历副本[:]或列表推导式 |
| 列表*陷阱 | [[0]*3]*3创建引用 | 列表推导式[[0]*3 for _ in range(3)] |
| 遍历时修改字典 | RuntimeError | 遍历list(dict.keys()) |
| unhashable key | 列表作为字典key | 使用元组代替列表 |
| 字符串不可变 | 尝试修改字符串 | 切片拼接或转换为列表 |
| 迭代器耗尽 | 生成器只能遍历一次 | 使用列表或重新创建 |
高级特性错误
| 错误 | 原因 | 解决 |
|---|---|---|
| 装饰器未返回 | 忘记return wrapper | 必须返回wrapper函数 |
| 元数据丢失 | 装饰器覆盖__name__ | 使用@wraps(func) |
| 裸except | 捕获所有异常 | 捕获Exception或特定异常 |
| 异常被吞没 | except: pass | 记录日志、重新抛出 |
| 忘记关闭文件 | 未调用close() | 使用with语句 |
| 上下文管理器 | __enter__未返回 | return self |
特殊场景错误
| 错误 | 原因 | 解决 |
|---|---|---|
| 相对导入 | 直接运行包内模块 | 使用绝对导入或python -m |
| *import 冲突 | 命名空间污染 | 导入模块或显式导入 |
| 浮点数精度 | 0.1+0.2!=0.3 | 使用Decimal或isclose() |
| 整数除法 | //和/混淆 | /浮点除,//整除 |
| 时区问题 | naive vs aware datetime | 统一使用timezone.utc |
| 正则未转义 | 特殊字符未转义 | 使用r""或re.escape() |
| 贪婪匹配 | .*匹配过多 | 使用.*?非贪婪 |
| JSON解析 | 单引号、尾逗号、空字符串 | try-except捕获JSONDecodeError |
| None操作 | 函数忘记return、sort()返回None | 检查None、使用返回值的函数 |
| 切片错误 | 步长为0、误用-1 | [::-1]反转、不能步长为0 |
| 集合unhashable | 列表作为集合元素 | 使用元组或frozenset |
| 字典合并 | dict1+dict2报错 | 使用|或{**d1,**d2} |
| 三元运算符 | 使用?:语法或顺序错误 | value_if_true if cond else value_if_false |
| f-string错误 | 花括号不匹配、反斜杠问题 | 检查语法、提前计算表达式 |
| 环境变量 | KeyError访问不存在的变量 | 使用os.getenv()提供默认值 |
| 推导式陷阱 | 闭包捕获、修改原列表 | lambda i=i:i、遍历副本 |
| 类型转换 | "False"是真值、"10">"9"是False | 显式转换、真值表 |
性能问题
| 问题 | 原因 | 优化方案 |
|---|---|---|
| 字符串拼接 | +=创建新对象 | 使用"".join() |
| 重复计算 | 递归无缓存 | 使用@lru_cache |
| 列表查找 | in操作O(n) | 使用set,O(1) |
| 不用推导式 | 循环append效率低 | 列表/字典推导式 |
| 重复len() | 循环中多次调用 | 提前计算并保存 |
附录C:预防错误的最佳实践
1. 代码风格
python
# 使用代码格式化工具
# pip install black autopep8
# 使用代码检查工具
# pip install pylint flake8
2. 类型注解
python
def add(a: int, b: int) -> int:
return a + b
3. 异常处理
python
# 不要过度使用try-except
try:
# 可能出错的代码
result = risky_operation()
except SpecificError as e: # 捕获特定异常
logging.error(f"错误: {e}")
result = default_value
4. 单元测试
python
import unittest
class TestCalculator(unittest.TestCase):
def test_add(self):
self.assertEqual(add(1, 2), 3)
def test_divide_by_zero(self):
with self.assertRaises(ZeroDivisionError):
divide(10, 0)
5. 代码审查
- 使用版本控制(Git)
- 进行代码审查
- 编写文档和注释
附录D:参考资源
- Python官方文档错误: https://docs.python.org/zh-cn/3/library/exceptions.html
- Stack Overflow: https://stackoverflow.com/questions/tagged/python
- Python调试技巧: https://realpython.com/python-debugging-pdb/
- Python最佳实践: https://docs.python-guide.org/
- Real Python教程: https://realpython.com/