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 编程中常见的容易出错的地方,理解并避免这些问题可以提高代码的质量和稳定性

相关文章

python之字典操作

字典的增删改方式方式一、[]处理法dict['name'] = 'tom' //如果当前key存在,则修改,如果不存在,则新增方式二、update函数功能:添加新的字典...

【Python进阶】巧用or运算符:赋值与逻辑判断的双重奏

引言在Python编程中,or运算符主要用于逻辑判断,用于连接两个布尔表达式,返回True只要其中一个表达式为真。然而,or运算符在Python中还有着更为巧妙的用法,即作为赋值操作的一部分,能够简化...

python的变量,变量赋值的一些规范

变量是什么,一般指的是存储的值会发生变化的内存地址,而为了方便编程,会用一个标识符(变量的名称)来表示这个内存地址,在python当中,没有指针这个概念,不必直接去操作内存,比如下面的代码(仅为个人理...

python字典dict添加元素的两种方法

python字典添加元素的两种方法要往python字典对象中添加元素(键值对),可以使用下方介绍的两种方法:使用dict字典内置的update()方法,该方法接收一个字典对象参数,并将参数中的元素添加...

3.2数据类型和变量赋值(JAVA程序员改行Python当天入门教程)

Python是一种动态类型的编程语言,它提供了丰富的数据类型用于存储和操作数据。在Python中,变量是用来存储数据的容器,而数据类型则定义了变量可以存储的数据种类和操作方式。本节将介绍Python中...

Python中复制字典并仅修改副本的方法

技术背景在Python编程中,当我们想要复制一个字典并对副本进行修改,而不影响原始字典时,可能会遇到一些问题。直接使用赋值语句 dict2 = dict1 并不能实现真正的复制,而是让 dict2 和...