1
qtd_packs = 2
size_pack = 16
pasta = []
pasta.append ('packs/krun/')
pasta.append ('packs/parting2/')

for k in range(0, qtd_packs):
    for n in range(1, size_pack+1):
        samples_in.append (pasta[k]+str(n)+'.wav')
    samples.append(samples_in)
    del samples_in[0:len(samples_in)]


print(samples)

我基本上是在尝试添加列表samples_in内部,然后删除旧列表以创建新列表。这将发生 2 次,因为. 但最后,我得到的是两个空列表:samples samples_inqtd_packs =2

[[], []]

在删除它之前,我已经删除appendsamples_in里面的samples内容。所以发生了什么事?

谢谢

4

3 回答 3

2

在 Python 中,列表是通过引用传递的。当您追加samples_in到 时,Python 会追加对samples的引用。如果要附加 to 的副本,可以执行以下操作:samples_insamplessamples_insamples

samples.append(samples_in[:])

这有效地从所有项目中创建了一个新列表,samples_in并将该新列表传递给samples.append(). 因此,现在当您清除 中的项目时samples_in,您并没有清除列表中附加的项目samples

另外,请注意这samples_in[:]相当于samples_in[0:len(samples_in)].

于 2013-08-15T23:25:47.663 回答
1

问题是在此之后:

samples.append(samples_in)

中新附加的值samples不是 的副本samples_in,而是完全相同的值。您可以从交互式解释器中看到这一点:

>>> samples_in = [0]
>>> samples = []
>>> samples.append(samples_in)
>>> samples[-1] is samples_in
True
>>> id(samples[-1]), id(samples_in)
(12345678, 12345678)

使用交互式可视化器可能更容易看到正在发生的事情。


因此,当您通过一个名称修改值时,如下所示:

>>> del samples_in[0:len(samples_in)]

通过两个名称可以看到相同的修改:

>>> samples[-1]
[]

一旦您意识到两个名称都指代相同的值,那应该是显而易见的。


作为旁注,del samples_in[:]会做与 完全相同的事情del samples_in[0:len(samples_in)],因为这些已经是切片的默认值。


如果您不希望这两个名称引用相同的值怎么办?然后你必须明确地制作一个副本。

copy模块具有可以复制(几乎)任何东西的功能,但许多类型都有更简单的方法来做到这一点。例如,samples_in[:]请求一个新列表,它将切片从 0 复制到末尾(同样,这些是默认值)。所以,如果你这样做了:

>>> samples.append(samples_in[:])

…你会有一个新的价值samples[-1]。同样,您可以轻松地进行测试:

>>> samples[-1], samples_in
([0], [0])
>>> samples[-1] == samples_in
True
>>> samples[-1] is samples_in
False
>>> id(samples[-1]), id(samples_in)
23456789, 12345678

而且,如果您更改一个值,则不会影响另一个值——毕竟,它们是单独的值:

>>> del samples_in[:]
>>> samples[-1], samples_in
([0], [])

但是,在这种情况下,您甚至不需要制作副本。您遇到问题的唯一原因是您试图samples_in一遍又一遍地重用。没有理由这样做,如果您samples_in每次都创建一个新值,那么问题就不会首先出现。而不是这个:

samples_in = []
for k in range(0, qtd_packs):
    for n in range(1, size_pack+1):
        samples_in.append (pasta[k]+str(n)+'.wav')
    samples.append(samples_in)
    del samples_in[0:len(samples_in)]

做这个:

for k in range(0, qtd_packs):
    samples_in = []
    for n in range(1, size_pack+1):
        samples_in.append (pasta[k]+str(n)+'.wav')
    samples.append(samples_in)
于 2013-08-16T00:21:35.653 回答
0

如果您希望样本包含两个列表,每个列表都有两个 qtd_packs 之一的字符串,beetea 下面的答案提供了解决方案:

qtd_packs = 2
size_pack = 16

pasta = []
pasta.append ('packs/krun/')
pasta.append ('packs/parting2/')

samples = []
samples_in = []
for k in range(0, qtd_packs):
    for n in range(1, size_pack+1):
        samples_in.append (pasta[k]+str(n)+'.wav')
    samples.append(samples_in[:])
    del samples_in[0:len(samples_in)]

print(samples)

产生这个输出:

[['packs/krun/1.wav', 'packs/krun/2.wav', 'packs/krun/3.wav', 'packs/krun/4.wav',
'packs/krun/5.wav', 'packs/krun/6.wav', 'packs/krun/7.wav', 'packs/krun/8.wav',
'packs/krun/9.wav', 'packs/krun/10.wav', 'packs/krun/11.wav', 'packs/krun/12.wav',
'packs/krun/13.wav', 'packs/krun/14.wav', 'packs/krun/15.wav', 'packs/krun/16.wav'],
['packs/parting2/1.wav', 'packs/parting2/2.wav', 'packs/parting2/3.wav',
'packs/parting2/4.wav', 'packs/parting2/5.wav', 'packs/parting2/6.wav',
'packs/parting2/7.wav', 'packs/parting2/8.wav', 'packs/parting2/9.wav',
'packs/parting2/10.wav', 'packs/parting2/11.wav', 'packs/parting2/12.wav',
'packs/parting2/13.wav', 'packs/parting2/14.wav', 'packs/parting2/15.wav',
'packs/parting2/16.wav']]

现在,当我最初阅读您的问题时,我以为您正在尝试制作一个包含所有字符串的列表。在这种情况下,您可以使用

samples.extend(samples_in)

代替

samples.append(samples_in[:])

你会得到一个只包含字符串的平面列表。

于 2013-08-15T23:37:31.643 回答