Are python list comprehensions always a good programming practice?

Posted by dln385 on Stack Overflow See other posts from Stack Overflow or by dln385
Published on 2011-11-18T00:07:42Z Indexed on 2011/11/18 1:50 UTC
Read the original article Hit count: 145

To make the question clear, I'll use a specific example.

I have a list of college courses, and each course has a few fields (all of which are strings). The user gives me a string of search terms, and I return a list of courses that match all of the search terms. This can be done in a single list comprehension or a few nested for loops.

Here's the implementation. First, the Course class:

class Course:
    def __init__(self, date, title, instructor, ID, description, instructorDescription, *args):
        self.date = date
        self.title = title
        self.instructor = instructor
        self.ID = ID
        self.description = description
        self.instructorDescription = instructorDescription
        self.misc = args

Every field is a string, except misc, which is a list of strings.

Here's the search as a single list comprehension. courses is the list of courses, and query is the string of search terms, for example "history project".

def searchCourses(courses, query):
    terms = query.lower().strip().split()
    return tuple(course for course in courses if all(
            term in course.date.lower() or
            term in course.title.lower() or
            term in course.instructor.lower() or
            term in course.ID.lower() or
            term in course.description.lower() or
            term in course.instructorDescription.lower() or
            any(term in item.lower() for item in course.misc)
        for term in terms))

You'll notice that a complex list comprehension is difficult to read.

I implemented the same logic as nested for loops, and created this alternative:

def searchCourses2(courses, query):
    terms = query.lower().strip().split()
    results = []
    for course in courses:
        for term in terms:
            if (term in course.date.lower() or
                term in course.title.lower() or
                term in course.instructor.lower() or
                term in course.ID.lower() or
                term in course.description.lower() or
                term in course.instructorDescription.lower()):
                break
            for item in course.misc:
                if term in item.lower():
                    break
            else:
                continue
            break
        else:
            continue
        results.append(course)
    return tuple(results)

That logic can be hard to follow too. I have verified that both methods return the correct results.

Both methods are nearly equivalent in speed, except in some cases. I ran some tests with timeit, and found that the former is three times faster when the user searches for multiple uncommon terms, while the latter is three times faster when the user searches for multiple common terms. Still, this is not a big enough difference to make me worry.

So my question is this: which is better? Are list comprehensions always the way to go, or should complicated statements be handled with nested for loops? Or is there a better solution altogether?

© Stack Overflow or respective owner

Related posts about python

Related posts about coding-style