总结了十个 Python 高频错误,看看你中招了没
写 Python 时突然跳出一堆红色错误,是不是特让人头大?别慌,今天就来盘点 10 个大家最容易踩的坑,从新手常犯的语法错误到进阶时遇到的类型问题,一个个拆明白。学会这些,调试速度至少快一倍,再也不用对着错误提示发呆了!
先上个错误速查表
为了让大家有个整体印象,先放个表格汇总一下这 10 个高频错误:
错误类型 | 通俗解释 | 典型场景 | 一句话解决思路 |
---|---|---|---|
SyntaxError | 语法错误 | 少打括号、引号不匹配 | 检查拼写和标点符号 |
IndentationError | 缩进错误 | 空格和 Tab 混用、缩进不一致 | 统一用 4 个空格缩进 |
AttributeError | 属性错误 | 调用对象没有的方法 / 属性 | 先检查对象有没有这个属性再调用 |
ImportError | 导入错误 | 模块名写错、路径不对 | 检查模块名和安装情况 |
IndexError | 索引越界 | 列表索引超过范围 | 用 len () 查看长度再操作 |
KeyError | 字典键不存在 | 直接访问字典里没有的键 | 先用 in 判断或用 get () 方法 |
ValueError | 值错误 | 函数收到的值不对 | 检查传入函数的参数是否符合要求 |
TypeError | 类型错误 | 不同类型数据做运算 | 先做类型转换再操作 |
StopIteration | 迭代器错误 | 迭代器用完了还在用 | 用 for 循环自动处理迭代器 |
NotImplementedError | 未实现错误 | 抽象方法没重写 | 子类里一定要实现抽象方法 |
这应该是新手最常遇到的错误了,就好比写作文时出现了错别字或病句。Python 是个对语法很严格的语言,稍微写错一点就会报错。
# 少写了右括号
print("Hello World"
# 冒号忘写了
if 5 > 3
print("5比3大")
# 引号不匹配
print('Python真简单")
运行这些代码,都会出现SyntaxError
。
简单说就是代码不符合 Python 的语法规则。Python 对语法的要求特别严格,比如括号要成对出现、语句结束不需要分号但特定地方必须有冒号、字符串的引号要配对等等。
仔细检查报错信息里提示的行数,看看附近有没有拼写错误、遗漏的符号或者不正确的标点。建议写代码时边写边运行,不要等写了一大堆再运行,那样找错会很麻烦。
正确的代码应该是这样的:
# 正确写法
print("Hello World")
if 5 > 3:
print("5比3大")
print('Python真简单')
这个错误也是新手的重灾区,Python 用缩进来区分代码块,不像其他语言用大括号,所以缩进错了就会出问题。
# 缩进不一致
for i in range(5):
print(i)
print("循环中") # 这里缩进多了
# 混用空格和Tab
def add(a, b):
return a + b
print("函数定义完了") # 这里用了Tab而不是空格
Python 规定同一代码块必须有相同的缩进,而且要么全用空格,要么全用 Tab,不能混着用。通常推荐用 4 个空格作为缩进。
保持缩进一致,最好在编辑器里设置自动用空格代替 Tab。大多数 Python 编辑器都有这个功能,比如 VS Code、PyCharm 等。
正确示例:
# 正确写法
for i in range(5):
print(i)
print("循环中") # 和上面的缩进保持一致
def add(a, b):
return a + b
print("函数定义完了") # 函数外面的代码不需要缩进
这个错误就像是你想从苹果里找出橘子的特征,肯定找不到啊。当你试图访问一个对象没有的属性或方法时,就会报这个错。
# 访问不存在的属性
list1 = [1, 2, 3]
print(list1.length) # 列表没有length属性
# 调用不存在的方法
str1 = "hello"
str1.append("world") # 字符串没有append方法
上面的代码中,列表对象根本没有length
这个属性(列表用len()
函数来获取长度),字符串是不可变的,也没有append()
方法(这是列表的方法)。简单说,就是你想操作的属性或方法在这个对象上根本不存在。
先搞清楚你操作的对象是什么类型,这个类型有哪些属性和方法。可以用dir()
函数来查看一个对象有哪些属性和方法,比如dir(list1)
就会列出列表所有的属性和方法。
正确示例:
# 正确写法
list1 = [1, 2, 3]
print(len(list1)) # 用len()函数获取列表长度
str1 = "hello"
new_str = str1 + "world" # 字符串拼接用+号
print(new_str)
这个错误就像是你想去图书馆借一本书,但图书馆里根本没有这本书,或者你记错书名了。
# 模块名写错了
import numPy # 正确的是numpy
# 导入不存在的模块
import mymodule # 假设当前目录下没有mymodule.py
# 从模块中导入不存在的内容
from math import my_function # math模块里没有my_function
出现这个错误主要有几种情况:模块名拼写错误、模块没有安装、导入的内容在模块里不存在、模块路径不对(Python 找不到这个模块)。
首先检查模块名是否拼写正确,然后确认模块是否已经安装(如果是第三方模块,没安装的话用pip install 模块名
来安装)。如果是自己写的模块,要确保模块文件和你的代码在同一目录下,或者在 Python 的搜索路径里。
正确示例:
# 正确写法
import numpy # 正确拼写
# 先安装好requests模块,再导入
import requests
# 从math模块导入存在的函数
from math import sqrt # sqrt是math模块里的平方根函数
print(sqrt(16)) # 输出4.0
这个错误就像是你去超市买东西,货架上只有 5 个商品,你非要去拿第 6 个,那肯定拿不到啊。
# 列表索引超出范围
list1 = [1, 2, 3, 4, 5]
print(list1[5]) # 列表索引从0开始,最大索引是4
# 索引是负数且绝对值太大
print(list1[-6]) # 列表只有5个元素,最小负索引是-5
Python 中列表、元组等有序序列的索引是从 0 开始的,比如一个有 5 个元素的列表,索引是 0 到 4。如果你用了大于等于元素个数的索引,或者负数索引的绝对值大于元素个数,就会出现这个错误。
操作之前先确认序列的长度,用len()
函数可以获取长度。访问索引时,要确保索引在0
到len(序列)-1
之间,或者负索引在-len(序列)
到-1
之间。
正确示例:
# 正确写法
list1 = [1, 2, 3, 4, 5]
# 检查索引是否在有效范围内
index = 4
if 0 <= index < len(list1):
print(list1[index]) # 输出5
# 负索引正确用法
print(list1[-1]) # 输出5,-1表示最后一个元素
print(list1[-5]) # 输出1,-5表示第一个元素
这个错误就像是你查字典,想找一个字典里根本没有的字,那肯定查不到。
# 访问字典里不存在的键
dict1 = {"name": "张三", "age": 18}
print(dict1["gender"]) # 字典里没有gender这个键
字典是由键 - 值对组成的,当你用一个字典里不存在的键来访问时,就会出现这个错误。
访问字典的键之前,先检查这个键是否存在。有两种常用方法:一是用in
关键字判断,二是用字典的get()
方法。get()
方法如果键不存在,会返回None
或者你指定的默认值,而不会报错。
正确示例:
# 正确写法
dict1 = {"name": "张三", "age": 18}
# 方法一:用in判断
if "gender" in dict1:
print(dict1["gender"])
else:
print("字典里没有gender这个键")
# 方法二:用get()方法
print(dict1.get("gender")) # 输出None,不会报错
print(dict1.get("gender", "未知")) # 输出"未知",指定了默认值
这个错误就像是你去自动售货机买饮料,投了一张百元大钞,但售货机只接受硬币,它就没办法处理了。
# 函数收到的值不符合要求
num = int("abc") # int()函数不能把字母转换成整数
# 列表中找不到要移除的元素
list1 = [1, 2, 3]
list1.remove(4) # 列表里没有4这个元素
# 范围错误
import random
random.randint(5, 3) # 第一个参数必须小于等于第二个参数
这种错误是说函数收到的参数类型是对的,但值不合适。比如int()
函数可以处理字符串,但只能处理像"123"
这样的数字字符串,不能处理"abc"
这样的字母字符串。
调用函数时,要确保传入的值符合函数的要求。可以查看函数的文档,了解参数的取值范围和要求。对于可能出现的值错误,可以用try-except
语句来捕获并处理。
正确示例:
# 正确写法
# 转换字符串前先检查是否是数字
str1 = "123"
if str1.isdigit():
num = int(str1)
print(num)
else:
print("这个字符串不能转换成整数")
# 移除元素前先检查是否存在
list1 = [1, 2, 3]
if 4 in list1:
list1.remove(4)
else:
print("列表里没有这个元素")
# 正确使用random.randint()
import random
print(random.randint(3, 5)) # 第一个参数小于等于第二个参数
这个错误就像是你想把苹果和椅子加在一起,这两种不同类型的东西根本没法相加。
# 不同类型的数据做运算
num = 10 + "20" # 整数和字符串不能直接相加
# 函数参数类型不对
len(123) # len()函数需要传入可迭代对象,不能传整数
# 调用非函数的对象
list1 = [1, 2, 3]
list1() # 列表不是函数,不能像函数一样调用
这种错误是因为操作的数据类型不合适。比如,你不能把数字和字符串直接相加,不能对一个整数用len()
函数(因为len()
需要处理字符串、列表等可迭代对象)。
先确认你操作的数据类型是什么,然后检查这种操作是否适合这种数据类型。如果需要不同类型的数据一起操作,通常需要先进行类型转换。
正确示例:
# 正确写法
# 先做类型转换再运算
num = 10 + int("20") # 把字符串转换成整数再相加
print(num) # 输出30
# 给函数传入正确类型的参数
len("123") # 字符串是可迭代对象,可以用len()
print(len("123")) # 输出3
# 正确使用列表
list1 = [1, 2, 3]
print(list1[0]) # 访问列表元素,而不是把列表当函数调用
这个错误就像是你在电影院看电影,电影都已经放完了,你还非要接着看,那肯定什么都没有了。
# 迭代器用完了还继续调用next()
list_iter = iter([1, 2, 3])
print(next(list_iter)) # 输出1
print(next(list_iter)) # 输出2
print(next(list_iter)) # 输出3
print(next(list_iter)) # 迭代器已经用完了,再调用就会报错
迭代器是一个可以记住遍历位置的对象,它有一个__next__()
方法,每次调用都会返回下一个元素。当迭代器中的元素都被取完后,再调用next()
函数就会抛出StopIteration
错误。
在使用next()
函数之前,可以先判断迭代器是否还有元素。不过在实际编程中,我们很少直接用next()
函数来遍历迭代器,更多的是用for
循环,for
循环会自动处理迭代器的结束,不会出现这个错误。
正确示例:
# 正确写法
list_iter = iter([1, 2, 3])
# 用for循环遍历迭代器,自动处理结束
for item in list_iter:
print(item) # 依次输出1、2、3
# 或者用try-except捕获错误
list_iter2 = iter([1, 2, 3])
while True:
try:
print(next(list_iter2))
except StopIteration:
break # 迭代器用完了就退出循环
这个错误就像是老师布置了作业,但你根本没做,到交作业的时候自然就交不出来了。
# 抽象基类的方法没有在子类中实现
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
raise NotImplementedError("子类必须实现speak方法")
class Dog(Animal):
# 没有实现speak方法
pass
dog = Dog() # 创建对象时就会报错
dog.speak() # 即使能创建对象,调用这个方法也会报错
这个错误通常出现在面向对象编程中,当一个抽象基类定义了一个抽象方法(用@abstractmethod
装饰的方法),但继承它的子类没有实现这个方法时,就会出现这个错误。它其实是一个提醒,告诉你有事情还没做完。
只要在子类中实现父类的抽象方法就可以了。也就是说,子类必须定义和父类抽象方法同名的方法,实现具体的功能。
正确示例:
# 正确写法
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
raise NotImplementedError("子类必须实现speak方法")
class Dog(Animal):
# 实现父类的抽象方法
def speak(self):
return "汪汪汪"
class Cat(Animal):
# 实现父类的抽象方法
def speak(self):
return "喵喵喵"
dog = Dog()
print(dog.speak()) # 输出"汪汪汪"
cat = Cat()
print(cat.speak()) # 输出"喵喵喵"
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。