python最常见的几个错误,第4个百分之九十八都中过招
在 Python 编程里,即便有经验的开发者也可能在一些方面出错,下面为你详细介绍那些容易出错的高频场景
1. 可变默认参数问题
在 Python 里,函数的默认参数是在函数定义时就创建好的,而不是每次调用函数时创建。若默认参数是可变对象(像列表、字典),就会引发问题。
def add_item(item, my_list=[]):
my_list.append(item)
return my_list
print(add_item(1))
print(add_item(2))
在这个例子中,my_list 作为默认参数,在函数定义时就被创建了。每次调用函数时,若不提供新的列表,就会使用同一个列表对象,从而导致结果不符合预期。
解决办法:把默认参数设为 None,在函数内部创建新的可变对象。
def add_item(item, my_list=None):
if my_list is None:
my_list = []
my_list.append(item)
return my_list
print(add_item(1))
print(add_item(2))
2. 全局变量与局部变量混淆
在函数内部,若要修改全局变量,需要使用 global 关键字声明。否则,Python 会默认创建一个局部变量。
x = 10
def change_x():
x = 20
print(x)
change_x()
print(x)
在这个例子中,change_x 函数里的 x = 20 创建了一个局部变量 x,而不是修改全局变量 x。
解决办法:使用 global 关键字声明要修改的全局变量。
x = 10
def change_x():
global x
x = 20
print(x)
change_x()
print(x)
3. 循环中的变量作用域问题
在 Python 的循环里,循环变量的作用域是整个包含该循环的代码块,而非仅限于循环体。这可能会引发意外结果。
functions = []
for i in range(3):
functions.append(lambda: i)
for f in functions:
print(f())
在这个例子中,每个匿名函数都引用了同一个变量 i,当循环结束后,i 的值为 2,所以每个函数调用都会返回 2。
解决办法:通过函数参数来捕获循环变量的值。
functions = []
for i in range(3):
functions.append(lambda x=i: x)
for f in functions:
print(f())
4. 异常处理不当
在使用 try-except 语句时,若捕获的异常范围过大,可能会掩盖一些潜在的问题。
try:
result = 1 / 0
except Exception:
print("发生错误")
在这个例子中,except Exception 会捕获所有异常,包括一些可能是由其他原因导致的异常,这样就难以定位具体问题。
解决办法:尽量捕获具体的异常类型。
try:
result = 1 / 0
except ZeroDivisionError:
print("除数不能为零")
5. 浅拷贝与深拷贝混淆
在 Python 中,赋值操作只是创建了一个新的引用,而不是对象的副本。copy.copy() 进行的是浅拷贝,只会复制对象的一层结构,而 copy.deepcopy() 进行的是深拷贝,会递归复制对象的所有层次。
import copy
original_list = [[1, 2], [3, 4]]
shallow_copy = copy.copy(original_list)
shallow_copy[0][0] = 99
print(original_list)
在这个例子中,浅拷贝只复制了外层列表,内层列表仍然是同一个对象,所以修改浅拷贝的内层列表会影响原列表。
解决办法:若需要完全独立的副本,使用深拷贝
import copy
original_list = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(original_list)
deep_copy[0][0] = 99
print(original_list)
6. 迭代器和生成器使用不当
迭代器和生成器是 Python 中强大的特性,但如果使用不当,可能会导致意外结果。例如,迭代器只能遍历一次。
my_list = [1, 2, 3]
my_iterator = iter(my_list)
for num in my_iterator:
print(num)
for num in my_iterator:
print(num)
在这个例子中,第二次遍历迭代器时,由于迭代器已经耗尽,不会有任何输出。
解决办法:若需要多次遍历,重新创建迭代器或使用列表等可重复遍历的数据结构。
7. 字符串格式化问题
在 Python 中有多种字符串格式化方式,如 % 格式化、str.format() 和 f - 字符串。使用不当可能会导致语法错误或不符合预期的结果。
name = "Alice"
age = 25
# 使用 % 格式化
print("我叫 %s,今年 %d 岁。" % (name, age))
# 使用 str.format()
print("我叫 {},今年 {} 岁。".format(name, age))
# 使用 f - 字符串
print(f"我叫 {name},今年 {age} 岁。")
不同的格式化方式有不同的语法,需要根据具体情况选择合适的方式。
以上这些是 Python 编程中常见的容易出错的地方,理解并避免这些问题可以提高代码的质量和稳定性