3

如果列表项的日期是过去的(小于当前日期),我有一个过滤列表项的功能。

meetings = []
def clean_old():
    meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]

当列表为空时,此代码崩溃。

为什么会崩溃?它说for meeting in meetings,如果会议是空的,那么一切都应该没问题。

我该如何解决它,这种情况的解释是什么?

4

1 回答 1

7

我假设您看到此异常:

UnboundLocalError: local variable 'meetings' referenced before assignment

您在这里所经历的实际上与列表推导没有任何关系。发生此错误是因为您最初meetings在函数外部定义,但您试图在函数内部为其分配一个新值。

当 Python 看到一个变量在函数内被赋值时,它会将其视为一个新变量,特定于该函数。这可以防止函数从函数外部访问具有相同名称的任何变量。

在内部,Python 正在做类似这样的事情:

meetings_outside = []

def clean_old():
    meetings_inside = [meeting for meeting in meetings_inside if time.mktime(meeting) >= time.localtime()]

您可以理解为什么这会失败:meetings_inside是根据自身定义的。当 Python 尝试查找 的值meetings_inside以开始迭代其内容时,它失败了,因为它还没有被赋值。

如何处理这取决于您使用的 Python 版本,并且meetings定义了初始值。

在 Python 3 中,您可以简单地添加nonlocal meetings到函数的顶部。这将告诉它您指的是一个名为 的现有变量meetings,而不是创建另一个变量。

但是,您可能正在使用没有nonlocal关键字的 Python 2。它确实global关键字,它做同样的事情,但只有meetings在模块的顶层定义:在任何其他函数或类之外。

例如,如果您的文件中没有其他内容,这将在 Python 2 中工作:

进口时间

meetings = []

def clean_old():
    global meetings
    meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]

clean_old()
print meetings
[]

然而这不会,因为meetings是在函数内部定义的:

import time

def main():
    meetings = []

    def clean_old():
        global meetings
        meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]

    clean_old()
    print meetings

main()
NameError: global name 'meetings' is not defined

你需要解决这个问题。最简单的方法是将分配修改为:

 meetings[:] = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]

这告诉 Python 您正在替换 中的所有值meetings,但没有创建新list对象。(该语法称为“切片”,在 Python 教程中:有部分描述。)

于 2012-11-30T23:06:52.963 回答