Python 常见的10个错误:您在犯吗?

Python 常见的10个错误:您在犯吗?


发布日期: 2023-11-24 更新日期: 2023-11-24 编辑:xuzhiping 浏览次数: 284

标签:

摘要: 在本文中,我们分享了 2023 年 Python 常见的10个错误。但是这些常见的 Python 错误是什么呢?更重要的是,您在犯吗? 无论是像忘记冒号这样的初学者错误,还是像在迭代列表时修改列表这样更棘手的错误,在接下来的本文中都会深入探讨需要避免的新手错...

Python 常见的10个错误

在本文中,我们分享了 2023 年 Python 常见的10个错误。但是这些常见的 Python 错误是什么呢?更重要的是,您在犯吗?

无论是像忘记冒号这样的初学者错误,还是像在迭代列表时修改列表这样更棘手的错误,在接下来的本文中都会深入探讨需要避免的新手错误!同时提供了对每个常见 Python 错误的详细解释,以及避免这些错误的代码示例和最佳实践。因此,无论是初学者还是正在过渡到 Python 的专业人士,都可以继续阅读以了解如何避免这些常见的 Python 错误!

如何避免常见的 Python 错误?

无需多说,避免常见 Python 错误的最佳方法是在该语言的基础知识上打下坚实的基础。还应该通过构建 Python 项目定期编码,同时查看最佳实践。 像 linter 这样的 Python IDE 工具也是在潜在问题出现之前识别它们的好方法。如果看到一条弯曲的线,通常意味着可以从中学习一些东西!现在让我们深入研究 10 个最常见的 Python 错误,看看您是否犯了其中任何一个!

如何避免常见的 Python 错误

1.分配可变字典键

在 Python 中,字典键必须是不可变的。这意味着不能使用列表等可变类型作为字典键。如果尝试这样做,将会看到 TypeError。

这是为什么呢?答案很简单:字典依赖于散列,要求键是常量值以确保散列过程是可预测的。但如果使用可变对象,这些对象是可以更改的,这意味着它们的哈希值将是不可预测的,反过来又会损害字典的完整性。

接下来让我们看一个常见 Python 错误的示例,其中尝试使用列表作为字典键。

'''
Hackr.io: 10 Most Common Python Mistakes:
Assigning Mutable Dictionary Keys: Example
'''
my_lst = [1, 2, 3]
my_dct = {my_lst: 'value'}  # This will raise a TypeError

我们该如何解决这个问题?如果需要使用集合作为字典键,请使用元组!这本质上是一个不可变的列表,使其成为理想的替代品。换言之,重要的是要记住元组的元素也必须是不可变的,元组才能是可散列的!

例如,如果有一个列表元组,这也会是一个问题。

'''
Hackr.io: 10 Most Common Python Mistakes:
Assigning Mutable Dictionary Keys: Solution
'''
my_tup = (1, 2, 3)
my_dct = {my_tup: 'value'}  # This is the correct approach

2.调用函数时忘记括号

在 Python 中,函数是一等对象。这意味着它们可以被传递、分配给变量等等,就像处理字符串、整数、列表等一样。 然而当引用不带括号的函数时,是在引用该函数对象,而不是调用它。

对于初学者来说,这是一个非常常见的 Python 错误,如果不理解其中的细微差别,它可能会导致一些意外的行为或错误。让我们看一个简单的例子来说明这一点。下面代码示例可以看到,当引用函数对象并打印时,得到了函数对象的内存位置。

'''
Hackr.io: 10 Most Common Python Mistakes:
Forgetting Parentheses To Call Functions: Example
'''
def greet():
  return 'Hello!'

message = greet 
# This assigns the function object to the variable, not its return value
print(message) 
# This will print something like: <function greet at 0x7f4c6d0d59d0>

但如果想调用函数并获取其返回值,请在函数名称后使用括号,如下面的解决方案所示。

'''
Hackr.io: 10 Most Common Python Mistakes:
Forgetting Parentheses To Call Functions: Solution
'''
def greet():
  return 'Hello!'

message = greet() 
# This calls the function and assigns its return value to the variable
print(message) 
# This will print: Hello!

因此,主要的要点是括号对于区分引用函数和调用函数至关重要

3.忘记冒号

在 Python 中,冒号表示新代码块的开始,无论是函数、条件语句、循环还是其他控制结构。

无论您是 Python 初学者还是从其他语言过渡,忘记添加冒号都可能是 Python 的常见错误。 但如果没有冒号,Python 就无法将后续的缩进块识别为属于控制结构,从而导致语法错误。让我们看一下这个常见 Python 错误的一些示例。

'''
Hackr.io: 10 Most Common Python Mistakes:
Forgetting Colons: Example
'''
def greet()   # Missing colon here
  return 'Hello!'

if True    # Missing colon here
  print('This is true!')

for i in range(3)   # Missing colon here
  print(i)

但值得庆幸的是,这些都非常容易修复,如下面的代码解决方案所示。

'''
Hackr.io: 10 Most Common Python Mistakes:
Forgetting Colons: Solution
'''
def greet():  # Corrected with a colon
  return 'Hello!'

if True:  # Corrected with a colon
  print('This is true!')

for i in range(3):  # Corrected with a colon
  print(i)

正如您所看到的,只需要记住在开始新的缩进块之前在行尾添加冒号即可。

4.连接字符串和整数

在 Python 中,数据类型是严格强制的,这意味着如果不显式转换其中一种类型,则无法连接字符串和整数。

对于依赖 Python 动态类型的多功能性的初学者来说,这是一个常见的 Python 错误,但它总是会导致 TypeError。让我们看一个简单的例子来说明这个错误,可看到我们尝试将两个字符串对象与一个整数连接起来。

从表面上看,这似乎很好,因为我们只想创建一个新的字符串对象,但使用这种方法 我们总是会看到 TypeError 。

'''
Hackr.io: 10 Most Common Python Mistakes:
Concatenating Strings And Integers: Example
'''
age = 25
message = 'I am ' + age + ' years old.'  # This will raise a TypeError

幸运的是,这是一个很容易修复的 Python 错误,如下面的解决方案所示,其中我们提供了两种方法。

第一种从整数变量的类型转换开始,因为这会将整数转换为字符串,从而允许无错误地连接。第二种有时更方便的方法是使用格式化字符串文字,或更简洁地说,使用 f 字符串。

在这里,可以通过将整数变量直接添加到字符串输出中来完全避免连接,只需要使用大括号作为占位符。这绝对是我希望早点知道的 Python 概念之一!

'''
Hackr.io: 10 Most Common Python Mistakes:
Concatenating Strings And Integers: Solution
'''
age = 25

# Using str() to convert the integer
message_1 = 'I am ' + str(age) + ' years old.'
print(message_1)  # Outputs: I am 25 years old.

# Using formatted string (f-string in Python 3.6+)
message_2 = f'I am {age} years old.'
print(message_2)  # Outputs: I am 25 years old.

主要要点是连接字符串和整数时需要谨慎对待数据类型。如果确实需要这样做,请使用 Python 的类型转换来组合字符串和整数。

5.令人困惑的等式和赋值运算符

作为 Python 中使用最广泛的两个运算符,编程新手可能会发现很容易混淆 Python 等号 (==) 和赋值 (=) 运算符。这里的问题是相等运算符检查两个值是否相同,但赋值运算符将值分配给变量。 这意味着一个将返回布尔值,另一个仅执行赋值。

但是当尝试检查相等性时, 仍然很容易误用赋值运算符。如果确实犯了这个 Python 错误,将在程序中引入难以发现的错误或语法错误,这一点也不有趣!

让我们看一个简单的示例,看看这种常见的 Python 错误如何影响您的编程。在此示例中,要检查变量是否等于整数值,但在条件语句中使用了赋值运算符。

'''
Hackr.io: 10 Most Common Python Mistakes:
Confusing Equality And Assignment Operators: Example
'''

x = 5
if x = 10:  # This will raise a syntax error
  print('x is 10')
else:
  print('x is not 10')

幸运的是,这个 Python 错误非常容易修复,只需要用相等运算符替换赋值运算符即可。

'''
Hackr.io: 10 Most Common Python Mistakes:
Confusing Equality And Assignment Operators: Solution
'''

x = 5

# Correctly using the equality operator
if x == 10:
  print('x is 10')
else:
  print('x is not 10')

6.误解变量作用域

在 Python 中,变量作用域是代码中可以访问或修改变量的区域,这些区域往往是本地的或全局的。 对于 Python 初学者,尤其是那些从具有不同作用域规则的语言过渡的初学者来说,理解 Python 作用域可能很棘手!

当使用同名的局部变量和全局变量时,这一点变得尤其明显,因为局部变量将掩盖全局变量。 让我们看一个简单的例子来更清楚地理解这个 Python 错误。

该程序的目的是修改全局变量的值,我们将使用用户定义的函数来完成此操作。在这种情况下,定义了一个同名的全局变量和局部变量。这始终是一个糟糕的主意,但让我们看看接下来会发生什么。

当调用该函数时,打 印语句表明变量值已更改。但是当使用另一个打印语句来检查全局变量的值时,我们可以看到它并没有改变,那么到底发生了什么呢?这里的问题是该函数仅修改局部变量,并且该变量在函数退出后不再存在。这意味着我们没有以任何方式修改或访问全局变量。

'''
Hackr.io: 10 Most Common Python Mistakes:
Misunderstanding Variable Scopes: Example
'''

x = 10  # Global variable

def change_x():
  x = 5  # Local variable with the same name
  print(f'Inside function: x = {x}')

change_x() # Output: Inside function: x = 5


print(f'Outside function: x = {x}') # Output: Outside function: x = 10

那么如何解决这个常见的 Python 错误?让我们看一下使用两种不同方法的代码解决方案。

首先,可以使用 global 关键字来访问局部函数作用域内的全局变量。这允许毫无问题地修改全局变量。第二种方法是将全局变量作为函数参数传递,允许在函数内修改全局变量。 还选择避免对局部变量和全局变量使用相同的名称,因为这始终是一个好习惯!

'''
Hackr.io: 10 Most Common Python Mistakes:
Misunderstanding Variable Scopes: Solution
'''

# Solution 1: Using the 'global' keyword
x = 10

def change_global_x():
  global x
  x = 5
  print(f'Inside function (global x changed): x = {x}')
  # Output: Inside function (global x changed): x = 5

change_global_x()
print(f'Outside function: x = {x}') # Output: Outside function: x = 5


# Solution 2: Using different names to avoid confusion
y = 10

def change_local_y(local_y):
  local_y = 5
  print(f'Inside function: local_y = {local_y}')
  # Output: Inside function: local_y = 5
  return local_y

y = change_local_y(y)
print(f'Outside function: y = {y}') # Output: Outside function: y = 5

关键要点是要谨慎对待变量名称及其范围,请记住函数内的局部变量将掩盖共享相同名称的全局变量。 当需要修改函数内的全局变量时,请使用 global 关键字或将变量作为函数参数传入。

7.迭代列表时修改列表

这是 Python 错误之一,除非遇到它,否则不会意识到这是一个问题,但当遇到它时,则会希望避免它!

问题是列表是可变的,因此它们的大小或顺序可以在迭代过程中发生变化,这使得跟踪当前元素索引或正在评估的项目变得很棘手。相信我,您确实想避免这个问题!

当有人开始使用 Python 时,以 IndexError的形式遇到了这个问题,却 无法弄清楚发生了什么。为了帮助避免这种常见的 Python 错误,让我们看一个简单的示例。

在此程序中,我们只是想从列表中删除所有偶数元素,使用条件检查和 del 语句来完成此操作。从表面上看,这种迭代列表并直接删除项目的方法似乎很好,但它会生成一个 IndexError。

为什么会出现这种情况?好吧,每次删除一个元素时列表都会缩小,但循环会继续使用原始列表 length中的原始索引。

'''
Hackr.io: 10 Most Common Python Mistakes:
Modifying A List While Iterating Over It: Example
'''

numbers = [1, 2, 3, 4, 5]
for i in range(len(numbers)):
  if numbers[i] % 2 == 0:  # Remove even numbers
      del numbers[i]

我们怎样才能修复这个 Python 错误呢?避免此问题的最简单方法是迭代 list 的副本,如下面的解决方案所示。

'''
Hackr.io: 10 Most Common Python Mistakes:
Modifying A List While Iterating Over It: Solution
'''

numbers = [1, 2, 3, 4, 5]
for num in numbers.copy():
  if num % 2 == 0:  # Remove even numbers
      numbers.remove(num)

print(numbers)  # Outputs: [1, 3, 5]

通过创建列表的副本,可以修改原始列表而不影响循环,从而避免 IndexError。

8.在列表推导式上使用循环

列表推导式可能是我本人最喜欢的 Python 语言功能之一,因为它们提供了一种简洁且可读的方式来创建列表。 也就是说,Python 新手常犯的一个错误是,当相同的代码可以通过列表推导式得到极大简化时,更倾向于使用传统循环。

毫无疑问,循环非常通用,它们使我们能够处理更复杂的逻辑,但列表推导对于简单的操作来说更加高效和可读。让我们看一个简单的例子来说明这一点。

在这个程序中,我们想要从另一个数字列表创建一个正方形列表,并且选择了标准的 for 循环来完成这项工作。

'''
Hackr.io: 10 Most Common Python Mistakes:
Using Loops Over List Comprehensions: Example
'''

numbers = [1, 2, 3, 4, 5]
squares = []
for num in numbers:
  squares.append(num * num)
print(squares)  # Outputs: [1, 4, 9, 16, 25]

现在,虽然代码是正确的,但它比必要的要冗长得多,使其不那么 Pythonic,因此是一个错误! 对于像这样的简单转换,可以使用列表理解来提供更简洁和 Pythonic 的解决方案,如下所示。

看看这段代码是多么的短小和简单!Pythonic 的定义!

'''
Hackr.io: 10 Most Common Python Mistakes:
Using Loops Over List Comprehensions: Solution
'''

# Using a list comprehension
numbers = [1, 2, 3, 4, 5]
squares = [num ** 2 for num in numbers]
print(squares)  # Outputs: [1, 4, 9, 16, 25]

9.不使用文档字符串

文档可能不是编码中最性感的部分,但它是任何代码库的重要方面,无论其大小如何。

无论您是正在学习 Python 课程的编码新手,还是正在切换语言的经验丰富的专业人士,文档字符串都是在代码中嵌入描述的理想选择。这使其他开发人员(以及未来的您)更容易理解特定函数、类或模块的操作方式。

然而尽管有明显的好处,但实际上遇到零文档的代码比您想象的更常见。 这是一个需要避免的 Python 错误!不仅是为了自己,更是为了团队的利益!

让我们看一个超级简单的例子来强调这一点,这显然是一个非常简单的计算矩形面积的函数。虽然看起来很简单,但没有文档字符串,关于预期参数类型、返回类型或用户应该注意的任何注意事项的信息为零。

'''
Hackr.io: 10 Most Common Python Mistakes:
Not Using Docstrings: Example
'''

def rectangle_area(width, height):
  return width * height

让我们看一个基本的文档字符串,它可以简单轻松地增强该函数的未来使用。通过添加基本文档字符串,任何阅读代码的人都会立即知道该函数的用途、其参数及其返回类型。

'''
Hackr.io: 10 Most Common Python Mistakes:
Not Using Docstrings: Solution
'''

def rectangle_area(width, height):
  """
  Calculates the area of a rectangle.

  Params:
  - width (float): The rectangle width.
  - height (float): The rectangle height.

  Returns:
  - float value: The area of the rectangle.
  """
  return width * height

主要课程是培养使用文档字符串记录代码的习惯,尤其是函数、类和模块。 这些增强了代码的可读性和可用性,使其更容易与他人协作,同时也使未来的代码维护更容易。 在专业环境中,记录良好的代码通常是质量的标志。

10.不处理异常

让我们通过异常处理来完成我们的常见 Python 错误列表。简而言之,异常处理对于创建健壮的 Python 应用程序至关重要。 如果不能优雅地预测和处理潜在的异常,代码可能会崩溃。

确实没有理由跳过开发过程的这一阶段。可以这样想:如果不处理异常,就会引入糟糕的用户体验、数据损坏和其他问题的可能性。如果您想成为一名专业编码员,需要花时间为您的程序添加异常处理。

让我们看一个简单的例子来说明这个常见的 Python 错误所带来的问题。在此程序中,当我们尝试除以零时,该函数会引发 ZeroDivisionError ,从而可能导致程序崩溃。

'''
Hackr.io: 10 Most Common Python Mistakes:
Not Handling Exceptions: Example
'''

def divide_numbers(numerator, denominator):
  return numerator / denominator

result = divide_numbers(10, 0)
print(result) # Throws ZeroDivisionError

怎样才能避免这种情况呢?让我们看一下使用 try- except 块来捕获潜在异常并妥善处理它们的解决方案。这是一种更具弹性的方法,由于通过处理异常,该函数现在可以提供有意义的反馈,而不是突然终止程序。

'''
Hackr.io: 10 Most Common Python Mistakes:
Not Handling Exceptions: Solution
'''

def divide_numbers(numerator, denominator):
  try:
      return numerator / denominator
  except ZeroDivisionError:
      return "Denominator cannot be zero."

result = divide_numbers(10, 0)
print(result)  # Outputs: Denominator cannot be zero.

了解代码可能引发的潜在异常并适当处理它们非常重要。 虽然使用广泛的 except 来捕获所有异常很诱人,但捕获和处理特定异常通常是更好的做法。通过这样做,可以避免掩盖可能潜伏的其他意外问题。

建议:在处理异常时始终努力提供反馈或后备解决方案,以确保您的应用程序保持用户友好和可靠。

经常问的问题

1.Python 中最常见的错误是什么?

如果我们谈论错误的类别,这些错误可能是语法错误或运行时异常。

如果我们指的是错误,一些最常见的错误是分配可变字典键、忘记调用函数的括号、忘记冒号、连接字符串和整数、混淆相等和赋值运算符,以及我们上面介绍的其他错误。

2.如何查找Python代码中的错误?

可以阅读错误消息、利用调试工具以及使用 IDE 工具(例如 linter 和静态代码分析器),还应该实施单元测试和代码审查来检查代码库是否有错误。如果允许的情况下也可以使用人工智能编码助手。

相关推荐

关注公众号
获取免费资源

随机推荐


Copyright © Since 2014. 开源地理空间基金会中文分会 吉ICP备05002032号

Powered by TorCMS

OSGeo 中国中心 邮件列表

问题讨论 : 要订阅或者退订列表,请点击 订阅

发言 : 请写信给: osgeo-china@lists.osgeo.org