I have a piece of code that works in Python 2.7 but not in Python3.7. Here I am trying to sort by values of a lambda function.
def get_nearest_available_slot(self):
"""Method to find nearest availability slot in parking
"""
available_slots = filter(lambda x: x.availability, self.slots.values())
if not available_slots:
return None
return sorted(available_slots, key=lambda x: x.slotNum)[0]
The error I get is:
File "/home/xyz/Desktop/parking-lot/parking-lot-1.4.2/parking_lot/bin/source/parking.py", line 45, in get_nearest_available_slot
return sorted(available_slots, key=lambda x: x.slotNum)[0]
IndexError: list index out of range
What am I doing wrong here?
The answer is simple: it's because of how filter
works.
In Python 2, filter
is eagerly evaluated, which means that once you call it, it returns a list
:
filter(lambda x: x % 2 == 0, [1, 2, 3])
Output:
[2]
Conversely, in Python 3, filter
is lazily evaluated; it produces an object you can iterate over once, or an iterator:
<filter at 0x110848f98>
In Python 2, the line if not available_slots
stops execution if the result of filter
is empty, since an empty list
evaluates to False
.
However, in Python 3, filter
returns an iterator, which always evaluates to True
, since you cannot tell if an iterator has been exhausted without trying to get the next element, and an iterator has no length. See this for more information.
Because of this, a case exists where an empty iterator gets passed to sorted
, producing another empty list
. You cannot access the element at position 0
of an empty list
, so you get an IndexError
.
To fix this, I suggest evaluating the condition strictly. You could do something like this, replacing sorted
with min
, since we only need one value:
def get_nearest_available_slot(self):
"""Method to find nearest availability slot in parking
"""
available_slots = [slot for slot in self.slots.values() if slot.availability]
if available_slots:
return min(available_slots, key=lambda x: x.slotNum)
else:
return None
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With