引言

 

Python 是一种非常强大的编程语言,它的语法很容易理解,即使你没有编程基础,也可以自学。在整个学习过程中,由于缺乏对某些概念的理解,你可能会犯很多错误。学习如何纠正这些错误将进一步增强你对基础知识以及编程技能的理解。

 

本文将总结许多人在开始学习过程中可能遇到的一些常见 Python 错误,以及如何修正或避免这些错误。

 

1. 修改后重新加载模块

 

你是否曾经浪费时间调试和修复一个问题,并最终意识到自己没有在修改后的源代码上进行调试?这种情况通常发生在初学者身上,因为他们没有意识到整个模块只在执行 import 语句时加载到内存中一次。因此,如果你正在单独的模块中修改某些代码并将其导入到当前代码中,则必须重新加载该模块以反映最新的更改。

 

要重新加载一个模块,你可以使用来自 importlib 模块的 reload 函数:

  •  
from importlib import reload # some module which you have made changes import externallib reload(externallib)

2. 全局变量和局部变量命名冲突

 

假设已经定义了一个名为 app_config 的全局变量,并且希望在 init_config 函数中使用它,如下所示:

  •  
app_config = "app.ini" def init_config():     app_config = app_config or "default.ini"     print(app_config)

你可能希望打印出 “app.ini”,因为它已经被全局定义,但是令人惊讶的是,由于变量 app_config 在赋值之前被引用,您会收到 “UnboundLocalError” 异常。如果注释掉赋值语句并仅打印出变量,将看到正确打印出的值。那么这是怎么回事?

 

这是由于每当有赋值表达式时,Python 都会尝试在局部作用域中创建一个变量,而且由于局部变量和全局变量具有相同的名称,全局变量被隐藏在局部作用域中。因此 Python 会抛出一个错误,说在初始化之前使用了局部变量 app_config。

 

为了解决这个命名冲突,你应该为你的全局变量和局部变量使用不同的名字来避免任何混淆,例如:

  •  
app_config = "app.ini" def init_config():     config = app_config or "default.ini"     print(config)

3.检查虚假值

 

在 if 或 while 语句中检查一个变量的真或假有时也会出错。对于 Python 初学者来说,混合 None 值和其他错误值并最终编写一些错误代码是很常见的。例如: 假设你想检查什么时候价格不是0或者低于5,触发一些卖出警告:

  •  
def selling_alert(price):        if price and price < 5:         print("selling signal!!!")

一切看起来都很好,但是当你用 price = 0进行测试时,你不会得到任何提醒:

  •  
selling_alert(0) # Nothing has been printed out

这是因为 Python 将 None 和0都计算为 False,因此打印语句将被跳过,尽管 price < 5为 true。

 

在 python 中,空序列对象,如“”(空字符串)、 list、 set、 dict、 tuple 等,都被计算为 False,在任何数字格式(如0和0.0)中也是零。因此,为了避免这样的问题,你应该非常清楚你的逻辑是否需要区分 None 和其他 False 值,然后在必要时分割逻辑,例如:

  •  
if price is None:     print("invalid input") elif price < 5:     print("selling signal!!!")

4.默认值和变量绑定

 

当你希望使函数参数可选但仍可灵活更改时,可以使用默认值。假设你需要实现一个带有 event_time 参数的日志记录函数,希望在未给出时将缺省值作为当前时间戳。你可以像下面这样写一些代码:

  •  
from datetime import datetime def log_event_time(event, event_time=datetime.now()):     print(f"log this event - {event} at {event_time}")

如果在 log_event_time 函数调用期间没有提供 event_time,那么在调用该函数时,它将用时间戳记记录事件。但是如果你用下面的方法来测试:

  •  
log_event_time("check-in") # log this event - check-in at 2021-02-21 14:00:56.046938 log_event_time("check-out") # log this event - check-out at 2021-02-21 14:00:56.046938

您将看到所有事件都以相同的时间戳记录。那么为什么 event_time 的默认值不起作用呢?

 

要回答这个问题,你应该知道变量绑定发生在函数定义期间。对于上面的示例,在最初定义函数时分配了 event_time 的默认值。每次调用函数时都会使用相同的值。

 

要解决此问题,可以将 None 设置为默认值,并检查它是否为 None 时覆盖函数调用中的 event_time 。例如:

  •  
def log_event_time(event, event_time=None):     event_time = event_time or datetime.now()     print(f"log this event - {event} at {event_time}")

5. 可变对象的默认值

 

Python 初学者容易犯的另一个错误是为可变函数参数设置默认值。例如, add_white_list 函数中的以下参数:

  •  
def add_white_list(user, user_list=[]):     user_list.append(user)     return user_list

你可能希望在未提供 user_list 的情况下创建一个空列表,然后将新用户添加到该列表中并返回。

  •  
my_list = add_white_list('Jack') # ['Jack'] my_list = add_white_list('Jill', my_list) #['Jack', 'Jill']

但是当你想再次使用空列表时,你会看到一些意想不到的结果:

 

从前面的变量绑定示例中,我们知道 user _ list 的默认值只在函数定义时创建一次。由于 list 是可变的,对 list 对象所做的更改将由后续的函数调用引用。

  •  
def add_white_list(user, user_list=None):     if user_list is None:         user_list = []         user_list.append(user)     return user_list

为了解决这个问题,我们将使用 None 作为 user _ list 的默认值,并在调用期间没有给出 user _ list 时使用局部变量创建一个新列表。例如:

 

·  END  ·