Any way to optimize or improve this python combinations/subsets functions? I believe this is essentially the same method as the itertools.combinations function, but is there any way to make this code more more perfect in terms of speed, code size and readability :

def all_subsets(source,size):
        index = len(source)
        index_sets = [()]
        for sz in xrange(size):
                next_list = []
                for s in index_sets:
                        si = s[len(s)-1] if len(s) &gt; 0 else -1
                        next_list += [s+(i,) for i in xrange(si+1,index)]
                index_sets = next_list
        subsets = []
        for index_set in index_sets:
                rev = [source[i] for i in index_set]
                subsets.append(rev)
        return subsets


Yields:

&gt;&gt;&gt; Apriori.all_subsets(['c','r','i','s'],2)
[['c', 'r'], ['c', 'i'], ['c', 's'], ['r', 'i'], ['r', 's'], ['i', 's']]


There is probably a way to use generators or functional concepts, hopefully someone can suggest improvements.
This type of problems lend themselves very well to recursion. A possible implementation, either in list or generator form could be:

def all_subsets(di, i) :
    ret = []
    for j, item in enumerate(di) :
        if i == 1 :
            ret = [(j,) for j in di]
        elif len(di) - j &gt;= i :
            for subset in all_subsets(di[j + 1:], i - 1) :
                ret.append((item,) + subset)
    return ret

def all_subsets_gen(di, i) :
    for j, item in enumerate(di) :
        if i == 1 :
            yield (j,)
        elif len(di) - j &gt;= i :
            for subset in all_subsets(di[j + 1:], i - 1) :
                yield (item,) + subset

&gt;&gt;&gt; all_subsets(range(4), 3)
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
&gt;&gt;&gt; list(all_subsets_gen(range(4), 3))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]


If you are going to run this on large sets, you may want to memoize intermediate results to speed things up.