I want to convert a generator or iterator to a list recursively.
I wrote the code below, but it looks naive and ugly and can be removed in doctest.
Q1. Help me in a good version.
Q2. How to indicate an object is immutable or not?
import itertools def isiterable(datum): return hasattr(datum, '__iter__') def issubscriptable(datum): return hasattr(datum, "__getitem__") def eagerlize(obj): """ Convert generator or iterator to list recursively. return a eagalized object of given obj. This works but, whether it return a new object, break given one. test 1.0 iterator >>> q = itertools.permutations('AB', 2) >>> eagerlize(q) [('A', 'B'), ('B', 'A')] >>> test 2.0 generator in list >>> q = [(2**x for x in range(3))] >>> eagerlize(q) [[1, 2, 4]] >>> test 2.1 generator in tuple >>> q = ((2**x for x in range(3)),) >>> eagerlize(q) ([1, 2, 4],) >>> test 2.2 generator in tuple in generator >>> q = (((x, (y for y in range(x, x+1))) for x in range(3)),) >>> eagerlize(q) ([(0, [0]), (1, [1]), (2, [2])],) >>> test 3.0 complex test >>> def test(r): ... for x in range(3): ... r.update({'k%s'%x:x}) ... yield (n for n in range(1)) >>> >>> def creator(): ... r = {} ... t = test(r) ... return r, t >>> >>> a, b = creator() >>> q = {'b' : a, 'a' : b} >>> eagerlize(q) {'a': [[0], [0], [0]], 'b': {'k2': 2, 'k1': 1, 'k0': 0}} >>> test 3.1 complex test (other dict order) >>> a, b = creator() >>> q = {'b' : b, 'a' : a} >>> eagerlize(q) {'a': {'k2': 2, 'k1': 1, 'k0': 0}, 'b': [[0], [0], [0]]} >>> test 4.0 complex test with tuple >>> a, b = creator() >>> q = {'b' : (b, 10), 'a' : (a, 10)} >>> eagerlize(q) {'a': ({'k2': 2, 'k1': 1, 'k0': 0}, 10), 'b': ([[0], [0], [0]], 10)} >>> test 4.1 complex test with tuple (other dict order) >>> a, b = creator() >>> q = {'b' : (b, 10), 'a' : (a, 10)} >>> eagerlize(q) {'a': ({'k2': 2, 'k1': 1, 'k0': 0}, 10), 'b': ([[0], [0], [0]], 10)} >>> """ def loop(obj): if isiterable(obj): for k, v in obj.iteritems() if isinstance(obj, dict) \ else enumerate(obj): if isinstance(v, tuple): # immutable and iterable object must be recreate, # but realy only tuple? obj[k] = tuple(eagerlize(list(obj[k]))) elif issubscriptable(v): loop(v) elif isiterable(v): obj[k] = list(v) loop(obj[k]) b = [obj] loop(b) return b[0] def _test(): import doctest doctest.testmod() if __name__=="__main__": _test()