[英]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
append
了samples
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.