Selection sort using recursion
def selection_sort(li, out=None):


I dislike the name "li," I think abbreviations are bad.

    if out is None:
        out = []    
        li = li[:]


Rather then using the out parameter to do this, I suggest creating a seperate internal function which is called. Otherwise, it looks like the caller to the function might reasonable pass out = something, when its only meant to be used internally.

    if len(li) == 0:
        return out


Better to use if not li:

    small = min(li)
    li.remove(small)
    out.append(small)
    return selection_sort(li, out)


Its a little hard to gauge this code because you are doing two things you shouldn't, using recursion when its not necessary and implementing your own sort routine. But if you are doing so for learning purposes that's fine.

EDIT

Iterative solution:

def selection_sort(li):
    li = li[:]
    out = []

    while li:
        smallest = min(li)
        li.remove(smallest)
        out.append(smallest)

    return out


But why is this better than the recursive solution:


There is a limit to your stack space. If you try to sort a large list using this function you'll get a RuntimeError
Calling a function has extra overhead that iterating in a loop does not, the iterative version will be faster
A loop is usually easier to read then recursion. The while loop makes it easy to see whats doing on, whereas the recursive version requires some thought about the code to see the logic.