Any way to optimize or improve this python combinations/subsets functions?
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.