附录C-Python常见错误与解决方案

目录

第一部分:基础错误(按出现频率排序)

  • [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)

常见原因:

  1. 变量名拼写错误
  2. 变量在使用前未定义
  3. 作用域问题(在函数外使用局部变量)

错误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:参考资源

相关推荐
joexk8 个月前
llamafactory-cli webui启动报错TypeError: argument of type ‘bool‘ is not iterable
webui·typeerror·llamafactory·nootbook
狮子座的男孩2 年前
webpack 解决:TypeError: merge is not a function 的问题
前端·vue.js·经验分享·webpack·node.js·浏览器控制台报错·typeerror