Python 类似于append行为的生成器表达式

Python 类似于append行为的生成器表达式,python,generator,Python,Generator,这与其说是一个实际问题,不如说是一个编程练习:我正在寻找一个类似于append行为的生成器表达式 考虑: def combine(sequence, obj): for item in sequence: yield item yield obj s = ''.join(combine(sequence, obj)) 此生成器基本上类似于append。在我的程序的工作流程中,以上速度与 sequence.append(obj) s = ''.join(sequ

这与其说是一个实际问题,不如说是一个编程练习:我正在寻找一个类似于
append
行为的生成器表达式

考虑:

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

s = ''.join(combine(sequence, obj))
此生成器基本上类似于
append
。在我的程序的工作流程中,以上速度与

sequence.append(obj)
s = ''.join(sequence)
我现在想知道是否有一个整洁的生成器表达式
genexpr

s = ''.join(genexpr)
这类似于上面的
append
行为,没有性能警告

s = ''.join(_ for a in [sequence, [obj]] for _ in a)
执行错误。

尝试使用来自
itertools
模块:

''.join(chain(sequence, [obj]))
如果您不想为
obj
创建新的
列表
,则可以尝试以下操作:

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

我会使用
[obj]
,因为它更具可读性,而且我怀疑
repeat
迭代器的开销是否比
list
创建要小。

我不确定您的具体示例,但我发现,即使使用大型列表,仅使用a+[b]也与其他方法一样快。以下是我的测试代码:

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)
以下是我的系统上的结果:

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

谢谢在我的代码的上下文中,这两个变体都与序列> AppOnter(Objo)相符合;s=''.join(sequence)@Jan PhilipGehrcke
append
可能会导致列表扩展(有时当用于追加新元素的可用空间不足时,会在后台进行扩展)。而
chain
只创建遍历现有元素的迭代器,因此不能进行任何内存重新分配。@Jan PhilipGehrcke这就是我的意思:“将项目附加到列表中所需的时间是“摊销常量”;每当列表需要分配更多内存时,它会为一些超出实际需要的项目分配空间,以避免在每次调用时必须重新分配内存(这假设内存分配器速度很快;对于大型列表,分配开销可能会将行为推向O(n*n))。“(from)@Jan PhilipGehrcke请查看。它解释了一些您可能感兴趣的深层细节。有趣的是,测试2和5在这里显示了相同的性能。是的,在我的代码中,使用
a+[b]
似乎很好。谢谢你指出这一点!现在,我不确定,你们中谁赢得了绿色复选标记。你们两位都提供了宝贵的见解。我们应该保持现状吗?:)我想ovgolovin回答了你的实际问题。仅供参考。