【问题标题】:python slice assignment of generator to list生成器的python切片分配到列表
【发布时间】:2012-08-06 07:29:49
【问题描述】:
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]

有人曾经告诉我切片分配已经到位。显然不是。有没有优雅的方法来实现它?

【问题讨论】:

  • @BrenBarn 你确定它应该从“slice”编辑到“splice”吗?
  • 是(或者更确切地说,从“拼接”到“切片”)。例如,参见docs.python.org/library/… 上的文档

标签: python list slice


【解决方案1】:

切片分配是就地分配的,但直到整个生成器都被消耗完才会发生分配。它不会一次将一个元素分配给列表。它会全部读取它们,然后一次性将它们全部粘贴到列表中。

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

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

【讨论】:

  • 对,在将列表放入 my_list 的意义上,它是“就地”,但是将生成器消耗到临时列表中会破坏“就地”的目的。谢谢,有道理。
【解决方案2】:

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

考虑:

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]

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

【讨论】:

    猜你喜欢
    • 2020-08-08
    • 1970-01-01
    • 2022-01-25
    • 2011-07-05
    • 1970-01-01
    • 2022-08-19
    • 2016-04-14
    相关资源
    最近更新 更多