python小白的问题?

aliens=[]
alien={'name':'big pig','color':'yellow','speed':'slow',}
for number in range(0,30):
aliens.append(alien)
for alien in aliens[0:15]:
print(alien)
print('\n\n')
for temp in aliens[0:2]:
if temp['color']=='yellow':
temp['color']='white'
for alien in aliens[:30]:
print(alien)
在python中输入了上面的代码,运行结果怎么把列表中的键‘color‘’值,全部改了,我的本意是改前2条字典中的值。我试了,如果把语句“alien={'name':'big pig','color':'yellow','point':5,'speed':'slow',}"放到第一个for循环里面就没有问题了,谁能告诉我是怎么回事?

你好,你这个问题其实也好理解:
for number in range(0,30):
aliens.append(alien)
你的这一步,目的是将aliens这个列表中追加30个相同的alien字典进去,在没有下面代码的时候,你把这两个语句执行完,输出aliens,确实可以看到你想要的结果,就是字典中有30个相同的alien字典。
但是重点是,如果你直接将alien这个字典名放进aliens.append()函数中作为参数,则向appens()函数中传的其实是alien在内存中的地址,即传址引用。举个例子来说:
有一个字典
dic = {'a':'b'} //此时内存分配给dic的地址比如说是0x11111111-0x22222222
有一个空列表li = []
我现在想向空列表li中追加2个相同的dic,则如果我写的是:
for i in range(2):
li.append(dic)
则此时相当于是将0x11111111-0x22222222这个地址追加进去了,也就是说这个for循环执行后,里面的两个元素读取的实际上都是0x11111111-0x22222222这个范围的数据。如此一来,在我没有修改li这个列表中字典键值的时候,输出li,我们看到的是两个元素是一样的,到现在一切还都正常。
但是因为两个元素读的都是0x11111111-0x22222222这个范围的内容,所以我们对每个li中的每个字典键值进行修改都会影响所有的列表元素中相应的键值。
解决办法:
很简单,直接将
aliens.append(alien)
改成
aliens.append(alien.copy())
----------
其实就是追加字典的时候,给字典多加了个copy()函数,但是意义就不同了,还是要从内存分配上想,这样一来,每次追加到aliens列表里的字典都是将alien这个字典在另一块内存放个备份,然后将备份的地址中的数据传给aliens列表。拿上面我举的li和dic的例来来说就是,原始dic的数据在内存中被分配的地址是0x11111111-0x22222222,则我向li中追加的时候我使用的是dic.copy(),则实现过程就相当于我把0x11111111-0x22222222给复制一份,比如说复制的这份被分配的内存为0x33333333-0x44444444,然后第2次追加的时候还是将0x11111111-0x22222222给复制一份,比如说这次的备份被分配的内存是0x55555555-0x66666666,则此时li中的两个元素,实际上第1个字典元素取的是0x33333333-0x44444444这个范围的地址;而第2个元素取的是0x55555555-0x66666666这个范围的地址,如此一来,由于列表li中每个字典元素的地址都是不同的,以后在对li中的每个字典元素进行修改的时候只会影响相应范围内的数据,也就互不干涉了.
哪块不明白,可以追问追问

大神,你的办法是可行的。你的意思基本可以理解?那么将第二句“alien={'name':'big pig','color':'yellow','speed':'slow',}”挪到第一个for循环里面来,为什么就可以呢?是不是python编译器在处理挪到for循环里面的“aliens.append(alien)”语句的时候,就不采用传递地址的方式了,而是使用了类似“aliens.append(alien.copy())”的处理方式。可以这样理解吗?

追答

你给出的代码中,“aliens.append(alien)”不就是在第1个for循环下吗?把代码贴出来看一下吧

温馨提示:答案为网友推荐,仅供参考
第1个回答  2019-12-20
如果是要改30个alien里面前两个的值,那么首先你要改的这两个alien是什么值;用列表切片[0:2]加上aliens[键]=新值就可以了。
第2个回答  2019-12-20
aliens=[] alien={'name':'big pig','color':'yell
相似回答