I want to convert generator or iterator to list recursively.
I wrote a code in below, but it looks naive and ugly, and may be dropped case in doctest.
Q1. Help me good version.
Q2. How to specify 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()