python字典inside / outside for循环

时间:2018-01-02 04:35:57

标签: python python-3.x python-2.7

我想更改字典中的一个元素但是如果我将new_alien放在循环之外,字典中的所有元素都会被更改。那是为什么?

#ALL aliens get changed when I put put the dictionary up here
new_alien = {'colour': 'green'}

aliens=[]

for alien_number in range(3):
    #if i put new_alien here only one alien dictionary gets changed in the for loop (correct code)
    #new_alien = {'colour': 'green'}
    aliens.append(new_alien)

print(aliens)

for alien in aliens[0:1]:
    if (alien['colour'] == 'green'):
        alien['colour'] = 'yellow'

print(aliens[0:2])

如果new_alien在循环之外,则输出:

[{'colour': 'green'}, {'colour': 'green'}, {'colour': 'green'}]
[{'colour': 'yellow'}, {'colour': 'yellow'}]

如果new_alien在循环内,则输出:

[{'colour': 'green'}, {'colour': 'green'}, {'colour': 'green'}]
[{'colour': 'yellow'}, {'colour': 'green'}]

注意循环外的所有外星字典:颜色变为黄色。 任何解释将不胜感激。谢谢!

6 个答案:

答案 0 :(得分:1)

Python Tutor是一款在线应用,可以向您展示会发生什么。您可以将代码粘贴到其中,并查看python解释器如何运行代码。

以下是纯文字的解释。

以下语句创建一个新的dict对象,而new_alien只是dict对象的引用。

new_alien = {'colour': 'green', 'points': 5, 'speed': 'slow'}

如果将this语句放在循环之外,则列表中的所有元素都引用相同的dict对象(或相同的内存空间),因为不为每个元素创建新的元素。

答案 1 :(得分:1)

如果您将new_alien放在外面,则会一遍又一遍地追加相同的对象。您可以使用id()打印出对象标识,以查看我的意思:

循环中

new_alien

for alien_number in range(3): 
    new_alien = {'colour': 'green', 'points': 5, 'speed': 'slow'}
    print(id(new_alien))
    aliens.append(new_alien)

输出不同的对象标识:

1577811864456
1577811864528
1577811864960

因此,您每次都会附加一个不同的对象。对new_alien的不同引用,3个单独的对象。如果更改一个对象,则此处只更改一个对象。这是执行此操作的正确方法。

循环外

new_alien

new_alien = {'colour': 'green', 'points': 5, 'speed': 'slow'}

for alien_number in range(3):
    print(id(new_alien))
    aliens.append(new_alien)

你得到相同的身份:

2763267730312
2763267730312
2763267730312

这意味着您反复追加同一个对象。这意味着如果更改一个对象,则所有对象都将更改。这是因为它们都是对一个对象的引用。如果你想在将来修改它们,那就不行了。

答案 2 :(得分:1)

案例1:因此,当您append new_alien = {'colour': 'green', 'points': 5, 'speed': 'slow'}进入列表时,它会引用相同的object内存。您可以通过id(Your_Object_Name)检查内存引用。基本上它就像一个全局变量。

案例2:当你尝试append从声明循环内部时,它会创建具有不同内存引用的不同对象。

答案 3 :(得分:1)

如果您将其放在外面,则会将相同的new_alien对象附加到aliens字典。如果您将其放入,则创建3个不同的new_alien对象,然后将其附加到aliens

for loop (correct code)
    new_alien = {'colour': 'green'}<-create a new dictionary {"c": "g"} and put it 
                                     under the name new_alien
    aliens.append(new_alien) # add the new dictionary

虽然它们都添加了相同的变量new_alien,但是在每轮循环期间绑定到new_alien的内容是不同的。每当您有new_alien的赋值语句(如new_alien = {'colour': 'green'})时,您(重新)绑定new_alien到新创建的字典。因此,稍后在aliens更改一个时,它不会影响其他人。

在另一种情况下:new_alien = {'colour': 'green'} 之外的循环中,相同的对象引用将被插入字典中3次。当您将其中一个更改为"yellow"时,您只需更改一个。 (实际上只有一个你可以改变它,即使它看起来有3个。)但是,当你打印它时,你也打印相同的字典存储 3次!这就是为什么它会给你相同的结果。

外卖

  • 对象可以具有所有引用它的不同名称。
  • 变量名称可以在不同时刻引用不同的对象。

在第一种情况下,new_alien引用不同的字典对象,而循环在每一步执行。

在后一种情况下,new_alien在循环之外,我们可以看到aliens[0]aliens[1]aliens[2]都引用相同的字典对象。您更改其中一个,是的,只更改了一个对象。你换了两个;仍然,一个相同的字典被更改。你读了所有三个;你只是三次读同一本字典。

答案 4 :(得分:0)

python中的对象被视为内存中的地址。因此,对象的变量名称只是对存储该对象的计算机内存中的位置的引用。如果你运行这行代码:

<form action="primary-page.php" id="primary_page">
    <input type="text" name="email" />
    <input type="submit" value="Submit" />
</form>

 1) data validate and stored in DB using ajax ( store-db.php ) 
 2) email value post to primary-page.php using function frm_submit()

var form_validate = $("#primary_page");
form_validate.validate({
    rules: {
        email: {
           required: true,
           email: true
        }
    },
    submitHandler: function () {
    var param = form_validate.serialize();
    var btn_submit = $("#submit");
    $.ajax({
        type: "POST",
        url: '/store-db.php',
        data: param,
        cache: false,
        dataType: "json",
        success: function (response) {
           frm_submit();
        }
   });
});


function frm_submit() {
  form = document.getElementById('primary_page');
  form.submit();
}

这会在内存中创建一个可由new_alien变量引用的对象。如果该行在循环之外,则它运行ONCE,而如果它在循环内部则运行多次。当这一行多次运行时,意味着在内存中创建了多个对象,但是当它运行一次时,只在内存中创建了一个对象,这就是为什么它们在外部声明时都会更新的原因;因为它们都引用了相同的内存位置。

答案 5 :(得分:0)

这称为浅拷贝,当您附加该项时,实际上是追加相同的对象,当您修改任何内容时,它将影响主对象:

  

解决方案:

你[co / sho]使用深度镜:

{display: block;}

输出:

from copy import deepcopy
#ALL aliens get changed when I put put the dictionary up here
new_alien = {'colour': 'green'}

aliens=[]

for alien_number in range(3):
    #if i put new_alien here only one alien dictionary gets changed in the for loop (correct code)
    #new_alien = {'colour': 'green'}
    aliens.append(deepcopy(new_alien))


for alien in aliens[0:1]:
    if (alien['colour'] == 'green'):
        alien['colour'] = 'yellow'

print(aliens[0:2])
print(new_alien)