Python implementation of Quicksort using list comprehensions
IMHO you can't really compare in-place quicksort to not-in-place quicksort. While the basic algorithm is the same, the implementation is vastly different, one being in-place (d'uh) and the other being much, much simpler.

Having said that, you could make your code a bit faster and (IMHO) cleaner by a) using wildcard-unpacking to separate the pivot from the rest (no need to slice the list twice), and b) return the list itself if it contains zero or one elements (no need to partition a one-elemented list).

def quicksort(lst):
    if len(lst) &lt;= 1:
        return lst
    else:
        p, *rest = lst
        low  = [x for x in rest if x &lt;= p]
        high = [x for x in rest if x &gt;  p]
        return quicksort(low) + [p] + quicksort(high)


The else is kind of redundant here, but IMHO it's cleaner that way.

However, using the first element of the list as pivot can be problematic if the list is already (partially) sorted, which is not uncommon. In this case, the performance will be much better/more predictable using a randomly chosen pivot (or any other method). This means that we have to partition the list into three parts, though, low, med, and high, otherwise we risk getting infinite recursion in case the list contains two or more copies of the pivot.

def quicksort(lst):
    if len(lst) &lt;= 1:
        return lst
    else:
        p = random.choice(lst)
        low  = [x for x in lst if x &lt;  p]
        med  = [x for x in lst if x == p]
        high = [x for x in lst if x &gt;  p]
        return quicksort(low) + med + quicksort(high)