Question: I'm 2 hours into my reading of *diveintopython* and I implemented a naive version of quicksort. 

```
import operator

def even(num):
    return operator.mod(num,2) == 0

def last(list):
    return len(list)-1

def median(list):
    if even(len(list)):
        return len(list)/2 - 1
    else:
        return len(list)/2

def sort(list, pivot_selector):
    if len(list) <= 1:
        return list
    else:
        i = pivot_selector(list)
        pivot = list[i]
        less, greater, equal = [], [], []
        for x in list:
            if x < pivot:
                less.append( x )
            elif x == pivot:
                equal.append( x )
            else:
                greater.append( x )

    return sort(less, pivot_selector) + equal + sort(greater, pivot_selector)

if __name__ == "__main__":
    print sort([5,4,3,2],median)
    print sort([],median)
    print sort([2],median)
    print sort([3,2],median)
    print sort([3,2,3],median)
    print sort([1,3,2],median)
    print sort([1,'a',0],median)
    print sort([None,1,0],median)

```

5 questions:

1. This code resides in a file called quicksort.py. How does one hide the method *even* from being exported to the public.
2. Is it pythonic to pass in a \*pivot\_selector\* as a parameter ?
3. Anything wrong or suboptimal with my quicksort implementation ?
4. How would you allow the user to specify a comparator that will enforce a custom ordering on the list elements ?
5. Is there a pythonic way to enforce a constraint that the list parameter must contain homogeneous types ?

Answer: 
Some semi-random notes on your code:

* Why the explicit `operator.mod` in `even` and not just `%` ?
* Is `len(list)/2 - 1` really important in `median`? If you have a list of length 4, why is index 2 any less a median than index 1? Also, `middle` would be a more suitable name, because the function doesn't really compute a *median*. Finding the real median in a list for quicksort is quite a complex issue and is usually approximated.
* Passing a selector as a function is quite Pythonic. You can use the same method to pass a comparison function and use it in `sort`.
* Your question (5) smells non-Pythonic - don't do that. Python is all about duck typing - if your user thinks he wants to compare integers to `class UserID` and provides the appropriate methods/operators, let him.
1. You don't hide things in Python, we are all consenting adults here. If you really don't want to export it, you could make it an inner function (declare it inside the function you are using it).
2. I don't see why it wouldn't be pythonic. Passing function parameters is commonly used through all the Python API (e.g. `sort`'s `key` argument)
3. Yes, your median should be called "middle". And of course, as you probably already know, you could sort it in place and replace recursion with a stack based iteration, that will be a little bit faster (as the call stack frames are heavier to push and pop than just the arguments than change).
4. The same as with your pivot selector argument, pass a function that takes two arguments and returns true if the arguments are in order.
5. No, but you can raise an exception if you wish. If you really, really want to, you can use **numpy** arrays, that are ensured to be homogeneous.