Python 在for循环外部声明变量(用于附加到列表)对列表中项目的后续操作有什么影响?

Python 在for循环外部声明变量(用于附加到列表)对列表中项目的后续操作有什么影响?,python,python-3.x,list,dictionary,for-loop,Python,Python 3.x,List,Dictionary,For Loop,我目前正在学习Eric Matthes的Python速成课程 我使用for循环将30个新项目添加到列表中。所有的项目都是字典。 然后,我尝试使用下面的代码更新列表的前几项—最后发布的实际代码- for item in items[0:3]: if item['someKey'] == 'someValue': item['someKey'] = 'someOtherValue' item['someOtherKey'] = 'someDifferentVa

我目前正在学习Eric Matthes的Python速成课程

我使用for循环将30个新项目添加到列表中。所有的项目都是字典。 然后,我尝试使用下面的代码更新列表的前几项—最后发布的实际代码-

for item in items[0:3]:
    if item['someKey'] == 'someValue':
        item['someKey'] = 'someOtherValue'
        item['someOtherKey'] = 'someDifferentValue'
因此,由于我只更改了前3项,它应该只更改前3项。但是,如果我在添加项时使用在for循环外部声明的变量追加到列表中,则会更改列表中的所有项

如果我运行这段代码,然后运行for循环来更新一些项目,那么列表中的所有项目都会被修改。使用[0:3]对列表进行切片不起作用

#Case-2
items = []
for item in range(30):
    dictionary = {'someKey': 'someValue', 'someOtherKey': 'someOtherValue'}
    items.append(dictionary)
因此,在本例中,更新过程按预期工作。for循环仅更新前3项。 为什么会发生这种情况?我不知道!在这两种情况下都可以创建列表。只有在修改已经创建的列表时,行为才会有所不同

这是实际的代码-

#Case-1
aliens = []
newAlien = {'color': 'green', 'speed': 'slow', 'points': 5}

for alienNumber in range(30):
   aliens.append(newAlien)

print(aliens) #Prints the whole list, showing adding dicts went just fine

for alien in aliens[0:3]: #intending change for only first 3 items
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10

for alien in aliens[0:5]:
    print(alien) #Shows all five items are modified even though intended for first 3
这就是事情的进展,很好-

#Case-2
aliens = []

for alienNumber in range(30):
    newAlien = {'color': 'green', 'speed': 'slow', 'points': 5}
    aliens.append(newAlien)

print(aliens) #prints whole list, 30 dicts are added

for alien in aliens[0:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10

for alien in aliens[0:5]:
    print(alien)  #Here only first 3 items are modified, as intended

在这里帮助我理解for循环的行为。循环只应添加项目,而不应添加其他内容。在for循环之外声明新字典如何改变以后修改项的方式

不要用变量来思考。从对象的角度思考

在定义notdeclare-python时,实际上没有变量声明——在循环之外的变量,只需创建一次对象,修改时该变量会一直引用同一个对象。然后继续向列表中添加相同的对象


在定义内部变量的情况下,每次迭代都会创建一个对象,每次迭代都会修改该新对象并将其添加到列表中。

不要用变量来思考。从对象的角度思考

在定义notdeclare-python时,实际上没有变量声明——在循环之外的变量,只需创建一次对象,修改时该变量会一直引用同一个对象。然后继续向列表中添加相同的对象

如果在内部定义变量,则在每次迭代中创建一个对象,该新对象将在每次迭代中修改并添加到列表中。

在案例1中,您在for循环外部定义了newAlien dictionary,因此,当您添加到列表中时,它将引用同一对象,当您在第二个for循环中将该对象值从绿色更改为黄色时,它将更改该对象的值。正如我所说,同一个对象是指所有,因此它将所有列表的所有值从绿色更改为黄色

在案例2中,您在循环中定义了newAlien dictionary,因此,在每次迭代中,newAlien将引用新对象,因此,当您将该值从绿色更改为黄色时,它将仅更改particuler elemnt的值,因为它引用的是不同的对象

试着打印newAlien的id,如下所示,并检查在案例1中是指相同的id,在案例2中是指不同的id

案例1

案例2

请在这两个代码上方运行,并查看print语句的输出。在案例1中,您在for循环外部定义了newAlien dictionary,因此,当您添加到列表中时,它将引用同一个对象,当您在第二个for循环中将该对象值从绿色更改为黄色时,它将更改该对象的值。正如我所说,同一个对象是指所有,因此它将所有列表的所有值从绿色更改为黄色

在案例2中,您在循环中定义了newAlien dictionary,因此,在每次迭代中,newAlien将引用新对象,因此,当您将该值从绿色更改为黄色时,它将仅更改particuler elemnt的值,因为它引用的是不同的对象

试着打印newAlien的id,如下所示,并检查在案例1中是指相同的id,在案例2中是指不同的id

案例1

案例2


请在这两个代码上面运行并查看print语句的输出

为了更好地理解,请尝试执行以下代码段:

案例3 外国人=[] newAlien={'color':'green','speed':'slow','points':5} 对于范围为30的alienNumber: 外星人 printaliens打印了整个列表,显示添加dicts很顺利 外星人[6]['color']='red' 外星人[6]['points']=8 外星人[6]['speed']='fast' 对于外人中的外人[0:5]: printalien显示所有五项都已修改,即使仅用于第七项。 解释

发生这种情况的原因并不是您修改了列表中的所有30个dict项。实际上,在本例中,您已经将newAlien字典的30个对象引用附加到了aliens列表中。因此,即使您修改了一个dict项,就像我在本例中尝试打印所有30项时所做的那样,它们也会 它们都是一样的,因此看起来都被修改了。实际上,有一个新的Alien dictionary对象,您已经对其进行了修改。现在,当您尝试使用30个对象引用中的任何一个来访问它时,您将只打印修改后的对象

即使在案例1中,if alien['color']='green':条件仅对alien列表中的第一项为真。然后修改newAlien对象,然后,所有30个项目的颜色属性都变为黄色。您可以通过在if子句内的循环中打印消息来验证,以查看条件计算为true的次数


在案例2中,每次循环迭代时都会创建一个新的newAlien对象,并存储对它们的引用。因此,有30个不同的newAlien字典,您可以独立于其他字典来更改其中一个。

为了更好地理解,请尝试执行以下代码段:

案例3 外国人=[] newAlien={'color':'green','speed':'slow','points':5} 对于范围为30的alienNumber: 外星人 printaliens打印了整个列表,显示添加dicts很顺利 外星人[6]['color']='red' 外星人[6]['points']=8 外星人[6]['speed']='fast' 对于外人中的外人[0:5]: printalien显示所有五项都已修改,即使仅用于第七项。 解释

发生这种情况的原因并不是您修改了列表中的所有30个dict项。实际上,在本例中,您已经将newAlien字典的30个对象引用附加到了aliens列表中。因此,即使你修改了一个dict项目,就像我在本例中尝试打印所有30个项目时所做的那样,它们都是相同的,因此看起来它们都被修改了。实际上,有一个新的Alien dictionary对象,您已经对其进行了修改。现在,当您尝试使用30个对象引用中的任何一个来访问它时,您将只打印修改后的对象

即使在案例1中,if alien['color']='green':条件仅对alien列表中的第一项为真。然后修改newAlien对象,然后,所有30个项目的颜色属性都变为黄色。您可以通过在if子句内的循环中打印消息来验证,以查看条件计算为true的次数


在案例2中,每次循环迭代时都会创建一个新的newAlien对象,并存储对它们的引用。因此,有30个不同的newAlien词典,您可以独立更改其中一个。

这类问题有一个规范的答案。见dupe。你不是第一个或最后一个在这个陷阱上绊倒的新手。@PatrickArtner我认为这不是一个好的复制品。这是关于列表重复操作符的。事实上,该操作符并没有要求它以这种方式工作,实现可以为您自动复制对象。您可以自由地实现自己的序列类型。也许在某个地方有更好的复制品…@truth也许你应该读一下:@juanpa newAlien={'color':'green','speed':'slow','points':5};对于范围为30的alienNumber:异形。appendnewAlien将同一词典引用多次添加到列表中。如果通过一个引用更改数据,则会更改所有引用指向的基础数据。这是一个完美的复制品。但还有一个这样的问题并不重要,已经有数千个了。@PatrickArtner是的,但这个副本并没有这样做,它在做[x]*y,这不是python引用如何工作的结果,而是列表中如何实现的结果。语言中没有任何东西可以阻止mul复制。这类问题有一个规范的答案。见dupe。你不是第一个或最后一个在这个陷阱上绊倒的新手。@PatrickArtner我认为这不是一个好的复制品。这是关于列表重复操作符的。事实上,该操作符并没有要求它以这种方式工作,实现可以为您自动复制对象。您可以自由地实现自己的序列类型。也许在某个地方有更好的复制品…@truth也许你应该读一下:@juanpa newAlien={'color':'green','speed':'slow','points':5};对于范围为30的alienNumber:异形。appendnewAlien将同一词典引用多次添加到列表中。如果通过一个引用更改数据,则会更改所有引用指向的基础数据。这是一个完美的复制品。但还有一个这样的问题并不重要,已经有数千个了。@PatrickArtner是的,但这个副本并没有这样做,它在做[x]*y,这不是python引用如何工作的结果,而是列表中如何实现的结果。语言中没有任何东西能阻止m 复制。
#Case-2
aliens = []

for alienNumber in range(30):
    newAlien = {'color': 'green', 'speed': 'slow', 'points': 5}
    aliens.append(newAlien)

print(aliens) #prints whole list, 30 dicts are added

for alien in aliens[0:3]:
    if alien['color'] == 'green':
        alien['color'] = 'yellow'
        alien['speed'] = 'medium'
        alien['points'] = 10

for alien in aliens[0:5]:
    print(alien)  #Here only first 3 items are modified, as intended
newAlien = {'color': 'green', 'speed': 'slow', 'points': 5}

for alienNumber in range(30):
   print(id(newAlien))
   aliens.append(newAlien)
for alienNumber in range(30):
    newAlien = {'color': 'green', 'speed': 'slow', 'points': 5}
    print(id(newAlien))
    aliens.append(newAlien)