2012-08-09 129 views
3
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] 

有人曾经告诉我,切任务是到位。很明显不是。有没有一种优雅的方式来实现它?

+1

@BrenBarn你确定它应该从“切片”编辑到“拼接”? – 2012-08-09 05:24:11

+1

是(或者说,从“拼接”到“切片”)。请参阅http://docs.python.org/library/stdtypes.html#sequence-types-str-unicode-list-tuple-bytearray-buffer-xrange – BrenBarn 2012-08-09 05:25:11

回答

6

切片分配就地,但分配不会发生,直到整个发生器被消耗。它不会一次将一个元素分配给列表。它将它们全部读取,然后将它们全部粘贴到列表中。 (请注意,它必须这样做,因为即使序列长度不同于原始片段,也可以将序列分配给片段,例如x[2:3] = [1, 2, 3, 4, 5, 6]。没有办法做到这一点一次替换一个元素,因为旧片和新片之间没有一对一的映射关系)

没有办法通过片分配来实现你想要的,因为切片分配总是以这种全部一次的方式工作。您将不得不并行地遍历列表和生成器,并逐个替换单个元素。

+0

上的文档。对,它在“位置”在将列表放入my_list中的感觉,但将生成器消耗到临时列表中会破坏“就地”目的。谢谢,有道理。 – 2012-08-09 05:29:28

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] 

当然,它是书面的方式,该列表将原来的列表或生成的元素的短。