Generator expression that resembles the behavior o

2019-05-08 05:44发布

问题:

This is more a programming exercise than a real-world problem: I am looking for a generator expression that resembles the behavior of append.

Consider:

def combine(sequence, obj):
    for item in sequence:
        yield item
    yield obj

s = ''.join(combine(sequence, obj))

This generator basically resembles append. In the workflow of my program the above is as fast as

sequence.append(obj)
s = ''.join(sequence)

I am now wondering if there is a neat generator expression genexpr with

s = ''.join(genexpr)

that resembles the append behavior above without performance caveats.

s = ''.join(_ for a in [sequence, [obj]] for _ in a)

performs bad.

回答1:

Try using chain from itertools module:

''.join(chain(sequence, [obj]))

If you don't want to create a new list for obj, then you may try this:

''.join(chain(sequence, repeat(obj,1)))

I would use [obj] as it's more readable and I doubt that repeat iterator has a less overhead than list creation.



回答2:

I'm not sure about your particular example, but I found that just using a+[b] was about as fast as anything else even with large lists. Here is my test code:

import timeit
from itertools import chain, repeat

a=map(str,range(100000))
b='b'

def combine(sequence,obj):
  for item in sequence:
    yield item
  yield obj

def test1():
  return ','.join(a+[b])

def test2():
  return ','.join(combine(a,b))

def test3():
  return ','.join(chain(a,repeat(b,1)))

def test4():
  return ','.join(chain(a,[b]))

def test5():
  return ','.join(y for x in [a,[b]] for y in x)

count=100
print 'test1: %g'%timeit.timeit(test1,number=count)
print 'test2: %g'%timeit.timeit(test2,number=count)
print 'test3: %g'%timeit.timeit(test3,number=count)
print 'test4: %g'%timeit.timeit(test4,number=count)
print 'test5: %g'%timeit.timeit(test5,number=count)

And here are the results on my system:

test1: 0.475413
test2: 0.977652
test3: 0.550071
test4: 0.548962
test5: 0.968162