I have a function that filters list items if their date is in the past (smaller than current date).
meetings = []
def clean_old():
meetings = [meeting for meeting in meetings if time.mktime(meeting) >= time.localtime()]
When the list is empty, this code crashes.
Why does it crash? It says for meeting in meetings, and if meetings is empty then everything should be alright.
How do I fix it and what is the explanation for that occurrence?
I assume that you are seeing this exception:
What you’re experiencing here doesn’t actually have anything to do with list comprehensions. This error occurs because you initially defined
meetingsoutside of your function, but you are trying to assign it a new value inside the function.When Python sees that a variable is assigned a value inside a function, it treats that as a new variable, specific to that function. This prevents the function from accessing any variables from outside of the function that have the same name.
Internally, Python is doing something sort-of like this:
You can understand why this would fail:
meetings_insideis being defined in terms of itself. When Python tries to look up the value ofmeetings_insideto begin iterating over its content, it fails because it hasn’t been assigned a value yet.How to deal with this depends on which version of Python you are using, and there the initial value of
meetingsis defined.In Python 3, you can simply add
nonlocal meetingsto the top of your function. This will tell it that you are referring to an existing variable namedmeetings, not creating another one.However you are probably using Python 2, which does not have the
nonlocalkeyword. It does have theglobalkeyword, which does the same thing but only ifmeetingsis defined at the top level of a module: outside of any other functions or classes.For example, this would work in Python 2 if you had nothing else in your file:
import time
However this would not, because
meetingsis defined inside of a function:You would need to work around the issue. The simplest way would be to modify the assignment to be:
This tells Python that you are replacing all of the values inside of
meetings, but aren’t creating a newlistobject. (The:syntax is called “slicing” and is partially described in the Python tutorial.)