繁体   English   中英

python中奇怪的列表行为

[英]Weird list behavior in python

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 列表中添加samples_in ,然后删除旧的samples_in列表以创建一个新的samples_in 这将发生2次,因为qtd_packs =2 但最后,我得到的是两个空列表:

[[], []]

在删除之前,我已经在samples appendsamples samples_in 所以发生了什么事?

谢谢

在Python中,列表通过引用传递。 samples_in附加到samples ,Python会将samples_in的引用附加到samples 如果要将samples_in的副本附加到samples ,可以执行以下操作:

samples.append(samples_in[:])

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

另请注意, samples_in[:]等同于samples_in[0:len(samples_in)]

问题是在此之后:

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)

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

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[:])

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM