python将生成器分配给列表

时间:2012-08-09 05:18:57

标签: python list slice

my_list = [1, 2]

def f():
    print my_list
    yield 11
    print my_list
    yield 22
    print my_list

my_list[:] = f()

print "finally ",
print my_list

输出:

[1, 2]
[1, 2]
[1, 2]
finally  [11, 22]

我的期望是:

[1, 2]
[11, 2]
[11, 22]
finally [11, 22]

有人曾告诉我切片分配到位。显然不是。是否有一种优雅的方式来实现它?

2 个答案:

答案 0 :(得分:7)

切片分配就位,但在整个生成器消耗之前不会进行分配。它不会一次为列表分配一个元素。它会全部读取它们,然后立即将它们全部放入列表中。

(请注意,它必须这样做,因为即使序列的长度与原始切片的长度不同,您也可以为切片指定序列。您可以这样做,例如,x[2:3] = [1, 2, 3, 4, 5, 6]。没有办法通过一次替换一个元素来做到这一点,因为旧切片和替换它的新序列之间没有一对一的映射。)

没有办法通过切片分配来实现您想要的效果,因为切片分配总是以这种一次性的方式工作。您必须并行迭代列表和生成器,并逐个替换单个元素。

答案 1 :(得分:1)

可以这样做,但不能直接做到。

考虑:

my_list = [1,2,3,4]

def f():
    print 'first: ', my_list
    yield 11
    print 'second:', my_list
    yield 22
    print 'third: ', my_list        

def inplace(l, func):
    gen=func()
    for i,x in enumerate(l):
        try:
            l[i]=gen.next()
        except StopIteration:
            if i<len(l):
                del l[i:]
            break     

inplace(my_list,f)

print     "final: ", my_list

打印:

first:  [1, 2, 3, 4]
second: [11, 2, 3, 4]
third:  [11, 22, 3, 4]
final:  [11, 22]

当然,编写它的方式,列表将是原始列表中的较短者或生成器中的元素。