【问题标题】:List on python appending always the same value [duplicate]python上的列表总是附加相同的值[重复]
【发布时间】:2016-06-24 16:51:44
【问题描述】:

我在 while 循环中有以下代码。

if gender == 0 and len(men) < 51 :
    height = float((random.uniform(1.3, 1.9) + (random.randint(10, 20)/100.)).__format__('.2f'))
    weight = float((random.uniform(45, 100) * height).__format__('.2f'))
    attr['height'] = height 
    attr['weight'] = weight

    men.append(attr)

所以这段代码总是给出一些随机的高度和随机的重量。但是在外部循环(完成时)。如果我这样做print men,我会得到以下结果:

[{'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}, {'weight': 76.64, 'height': 1.75}]

总是一样的。但是,如果我不使用attr[height] = height; attr['weight] = weight 而使用men.append(height); men.append(weight),我会得到以下结果:

print men [1.91, 145.95, 1.64, 95.66, 2.0, 159.94, 1.74, 143.36, 1.68, 97.99, 1.6, 90.11, 1.63, 116.2, 1.56, 96.8, 2.04, 198.56, 1.56, 145.96, 1.44, 67.57, 1.83, 94.97, 1.85, 175.69, 1.84, 101.84, 1.54, 135.0, 1.41, 101.23, 1.92, 167.59, 1.74, 142.55, 1.49, 129.07, 1.83, 161.28, 1.59, 97.16, 1.46, 134.53, 2.03, 158.72, 2.05, 184.43, 1.97, 162.81]

如果我在循环内打印 attr 它总是有不同的值(它是我想要的)。但是当我将它附加到我的列表时,我的列表的值总是相同的。我做错了什么?

【问题讨论】:

  • 请更新您的帖子并包含循环以获得清晰的图片。
  • 请修正你的缩进
  • 看起来你正在更新同一个字典,你可能只需要一个新的字典或副本,例如attr = {'height': height, 'weight': weight}men.append(attr.copy())

标签: python list python-2.7


【解决方案1】:

您的代码的简化示例目前可以更全面地解释为什么您的结果是这样的:

all_items = []
new_item = {}
for i in range(0,5):
    new_item['a'] = i
    new_item['b'] = i

    all_items.append(new_item)
    print new_item
    print hex(id(new_item))  # print memory address of new_item

print all_items

请注意,您的对象的内存地址是相同的每次您通过您的循环。这意味着每次添加的对象都是相同的。因此,当您打印最终列表时,您将在循环中的每个位置打印同一对象的坐标。

每次循环时,值都会更新 - 假设您每天都在同一面墙上作画。第一天,它可能是蓝色的。第二天,你重新粉刷同一面墙(或物体),然后它就变成了绿色。最后一天你把它涂成橙色,现在它是橙色的——同一面墙现在总是是橙色的。您对attr 对象的引用就像说您拥有相同的墙。

即使您在粉刷后看着墙壁,颜色也发生了变化。但之后它是一堵橙色的墙——即使你看了 5 次。

当我们在每次迭代中将对象作为一个新对象时,请注意发生了两件事:

  1. 内存地址改变
  2. 值作为唯一值保留

这类似于粉刷不同的墙壁。涂完最后一堵墙后,之前的每一面墙都还是你第一次涂的颜色。

您可以在下面看到这一点,其中每个对象都是在每次迭代中创建的:

all_items = []
for i in range(0,5):
    new_item = {}
    new_item['a'] = i
    new_item['b'] = i

    all_items.append(new_item)
    print hex(id(new_item))


 print all_items

你也可以用不同的方式来做,比如:

all_items = []
for i in range(0,5):
    new_item = {'a': i, 'b': i}
    all_items.append(new_item)
    print hex(id(new_item))    
print all_items

甚至一步:

all_items = []
for i in range(0,5):
    all_items.append({'a': i, 'b': i})

print all_items

因此,以下任一方法都可以:

attr = {}
attr['height'] = height 
attr['weight'] = weight

men.append(attr)

或:

men.append({'height': height, 'weight': weight})

【讨论】:

  • 谢谢,但我不明白为什么我使用 print attr。在循环内它显示了我想要的值,但是当我将它附加到列表时,它会附加错误值。
  • @Caaarlos 我添加了更多解释和类比,希望对您有所帮助。
  • 是的@enderland,它真的对我有帮助,你的解释和类比都太棒了!
【解决方案2】:

您多次将相同的attr 字典添加到列表中。以下行只会改变attr 字典,而不是创建一个新字典:

attr['height'] = height 
attr['weight'] = weight

你应该每次创建一个新的dict,例如:

attr = {'height': height, 'weight': weight}

【讨论】:

  • @AChampion 哈哈,是的,你用 30 秒击败了我。
【解决方案3】:

为了避免在循环中重新初始化(您错过的步骤)变量并将其附加到列表中所涉及的歧义,Python 允许您更加简洁。

height = float((random.uniform(1.3, 1.9) + (random.randint(10, 20)/100.)).__format__('.2f'))
men.append({
    'height': height,
    'weight': float((random.uniform(45, 100) * height).__format__('.2f')),
})

【讨论】:

  • 谢谢,它解决了我的问题。但是,你能更好地解释一下我做错了什么吗?感谢您教我更好的编程方式。
  • 我认为塞尔丘克的答案是您正在寻找的解释。当您的旧代码不起作用时,这会起作用的原因是它没有机会简单地更新现有字典中的值;始终通过 {} 语法隐式创建一个新的。
  • 当局部变量 'height' 不再被定义时,这如何工作?
  • 糟糕,点了。当您只是复制和粘贴而不阅读时会发生这种情况。 :) 我会编辑答案。
【解决方案4】:

您的问题是您正在改变 dict 并一遍又一遍地附加相同的 dict。你应该每次都创建一个新的字典

使用round而不是转换为str再返回float也更清晰

if gender == 0 and len(men) < 51 :
    height = round(random.uniform(1.3, 1.9) + (random.randint(10, 20)/100.), 2)
    weight = round(random.uniform(45, 100) * height, 2)
    men.append({'height' : height, 'weight', weight})

【讨论】:

    【解决方案5】:

    你应该在 for 循环内而不是在 for 循环外使用字典的定义

    for i in range(0, 10):
        attr = {}
        if gender == 0 and len(men) < 51 :
            height = float((random.uniform(1.3, 1.9) + (random.randint(10,20)/100.)).__format__('.2f'))
            weight = float((random.uniform(45, 100) * height).__format__('.2f'))
            attr['height'] = height 
            attr['weight'] = weight
    
            men.append(attr)
    

    这给了我以下输出:

    [{'weight': 126.75, 'height': 1.76}, {'weight': 155.35, 'height': 1.91}, {'weight': 169.2, 'height': 1.87}, {'weight' :135.54,“身高”:1.45},{“体重”:98.58,“身高”:1.98},{“体重”:133.73,“身高”:1.44},{“体重”:149.48,“身高”:1.87 }, {'weight': 121.93, 'height': 1.46}, {'weight': 160.09, 'height': 1.93}, {'weight': 115.62, 'height': 1.56}]

    【讨论】:

    • 对不起,这是一个错误,现在已经更正了。谢谢
    猜你喜欢
    • 2020-09-24
    • 2013-12-23
    • 2013-02-25
    • 2019-03-16
    • 2013-06-18
    • 2013-04-17
    • 2010-12-11
    相关资源
    最近更新 更多