编程中常见错误的例子 (Part 1)
大家好,今天讲几个编程中的常见错误的例子。
示例 1:在迭代列表时修改列表
- 问题:此示例中,代码在迭代列表 'items' 时尝试删除其中的元素。这可能导致跳过某些元素或引发 IndexError,因为列表的大小在迭 代过程中发生了变化。
- 正确方法:创建一个新列表或使用列表推导式来过滤元素,或者使用 items[:] 迭代列表的副本。
示例 2:使用可变的默认参数
- 问题:函数 'add_item' 使用了可变的默认参数 'list_items=[]'。在 Python 中, 默认参数只在函数定义时评估一次, 而不是每次调用函数时都重新评估。 这意味着所有未指定 'list_items' 的 'add_item' 调用都会修改同一个列表,导致意外的元素累积。
- 正确方法:使用 None 作为默认参数,并在函数内部如果参数为 None 时初始化一个空列表。
示例 3:与 None 进行错误的比较
- 问题:代码检查 'value == False',但 'value' 是 None。在 Python 中,None 不等于 False, 使用 '==' 与 None 进行比较可能导致逻辑错误,因为 None 是一个独立的类型。
- 正确方法:使用 'is None' 显式检查 None,这是 Python 中的惯用方式,避免与其他 falsy 值混淆。
示例 4:浮点数的相等比较
- 问题:代码尝试直接比较浮点数 'a = 0.1 + 0.2' 和 'b = 0.3' 是否相等。 由于浮点数在计算机中的表示存在精度问题,这种直接比较通常会失败,即使从数学上看它们应该相等。 这可能导致逻辑错误。
- 正确方法:避免直接比较浮点数是否相等, 而是检查它们之间的差值是否小于一个很小的阈值(例如使用 math.isclose() 函数)来判断是否“足够接近”。
示例 5:误解循环中的变量作用域与闭包
- 问题:函数 'create_functions' 在循环中创建函数并将其添加到列表中, 但由于闭包特性,每个函数都引用了循环变量 'i' 的最终值,而不是循环中每次迭代的值。 这导致所有函数返回相同的值(循环结束时的 'i' 值),而不是预期的不同值。
- 正确方法:使用工厂函数或立即执行的 lambda 表达式来捕获每次迭代的值, 或者在循环中使用局部变量来避免闭包引用循环变量的最终值。
代码示例
# Example 1: Modifying a list
# while iterating over it
items = ['A', 'B', 'C', 'D', 'E']
for item in items:
if item == 'B':
items.remove('B')
else:
print(item)
# print A D E
# Example 2: Using mutable default arguments
def add_item(item, list_items=[]):
list_items.append(item)
return list_items
# print [1]
print(add_item(1))
# print [1,2]
print(add_item(2))
# Example 3: Incorrect use of
# comparison with None
value = None
if value == False:
print("Value is False")
else:
print("Value is not False")
#print Value is not False
# Example 4: Equality comparison
# with floating-point numbers
a = 0.1 + 0.2
b = 0.3
if a == b:
print("a equals b")
else:
print("a does not equal b")
#print a does not equal b
# Example 5: Misunderstanding variable scope
# in loops with closures
def create_functions():
funcs = []
for i in range(3):
def func():
return i
funcs.append(func)
return funcs
for f in create_functions():
# Prints 2, 2, 2 instead of 0, 1, 2
print(f())