itertools.flatten()? and copying generators/iterators.
Peter Otten
__peter__ at web.de
Wed Oct 29 10:57:05 EST 2003
Alex Martelli wrote:
> The key thing is watching for difference in big-O behavior --
> and, here, we have none... just somewhat different (NOT
> by whole orders of magnitude!) multiplicative constants.
> THAT kind of performance issue is one we can live with
> more often than not! Which, in turn, is what makes the
> ordinary use of exceptions generally tolerable from the
> point of view of performance, except in the very hottest
> bottlenecks...
You are right, but let me play a little with the code anyway:
def flatten_am(s):
try:
s+''
except TypeError:
try: it = iter(s)
except TypeError:
yield s
else:
for elem in s:
for subelem in flatten_am(elem):
yield subelem
else:
yield s
def flatten_dict(s, isScalar):
try:
scalar = isScalar[s.__class__]
except KeyError:
t = s.__class__
try:
s = iter(s)
except TypeError:
scalar = isScalar[t] = True
else:
scalar = isScalar[t] = False
if scalar:
yield s
else:
for elem in s:
for subelem in flatten_dict(elem, isScalar):
yield subelem
# an example tree -- a mix of strings, items, some nesting
subtree = ['foo']*18 + [1,2,3]*6
tree = [ subtree*10, [ subtree * 8 ] ]
def pro_am():
for f in flatten_am(tree): pass
def pro_dict():
for f in flatten_dict(tree, {"".__class__: True}): pass
assert list(flatten_am(tree)) == list(flatten_dict(tree, {"".__class__:
True}))
This gives for flatten_am()
...> timeit.py -c -s"import fl" "fl.pro_am()"
100 loops, best of 3: 5.7e+03 usec per loop
versus
...> timeit.py -c -s"import fl" "fl.pro_dict()"
1000 loops, best of 3: 1.37e+03 usec per loop
for flatten_dict(). So you get some speed up at the cost of uglier though
still quite readable code and under the assumption that either all or no
instances of a class are iterable.
Of course the idea works with both isinstance() and a + "" but seems
somewhat more in the spirit of isinstance().
Peter
More information about the Python-list
mailing list