带有列表值的python字典 - 使用列表更新一个键会更新具有相同列表的所有键

时间:2018-03-05 17:11:24

标签: python python-3.x list dictionary

我是python词典的新手,所以我不确定为什么会这样。基本上问题是每当我用列表更新密钥时,它都会用列表更新该字典中的所有密钥。 尝试,除了只有独特的用户,所以我不认为这是问题

    file:
    user contact
    20b3c296-0043-3948-9c90 Stacy Armstrong
    20b3c296-0043-3948-9c90 Brian Theresa
    20b3c296-0043-3948-9c90 Miller Justin
    c9b16828-91d2-33c9-b915 Monique Porter
    c9b16828-91d2-33c9-b915 Rebecca Marky
    c9b16828-91d2-33c9-b915 Rose Chang
    a6f8a71d-7568-3552-9cf4 Mildred Linda
    a6f8a71d-7568-3552-9cf4 Josephine Larry
    a6f8a71d-7568-3552-9cf4 Henry Mildred

以下是代码:

for row in file:
    user = get_user(row)
    contact = get_contact(row)
    try:
        a = list_users.index(user)
    except ValueError:
        list_users.append(user)

        if len(list_users) > 1: # start from second user, and update previous one
            index = list_users.index(user)
            prev_user = list_users[index - 1]

            user_contacts.update({prev_user: list_contacts})    # update previous user with its list

            # print dict
            for key, value in user_contacts.items():
                print(key, value)
            print('\n')

        # clear list and add new contact (associated with new user)
        list_contacts.clear()
        list_contacts.append(contact)

    else:
        list_contacts.append(contact)

# update last user with its list
index = len(list_users)
prev_user = list_users[index - 1]

user_contacts.update({prev_user: list_contacts})

# print dict
for key, value in user_contacts.items():
    print(key, value)
print('\n')

印刷语句给我:

20b3c296-0043-3948-9c90 ['Stacy Armstrong', 'Brian Theresa', 'Miller Justin']


20b3c296-0043-3948-9c90 ['Monique Porter', 'Rebecca Marky', 'Rose Chang']
c9b16828-91d2-33c9-b915 ['Monique Porter', 'Rebecca Marky', 'Rose Chang']


20b3c296-0043-3948-9c90 ['Mildred Linda', 'Josephine Larry', 'Henry Mildred']
c9b16828-91d2-33c9-b915 ['Mildred Linda', 'Josephine Larry', 'Henry Mildred']
a6f8a71d-7568-3552-9cf4 ['Mildred Linda', 'Josephine Larry', 'Henry Mildred']

尽管list_contacts每次都不同(您可以在更新字典之前尝试打印),但所有键值都会更新到该迭代中的最后一个列表。非常感谢任何帮助,因为我真的不知道这是什么原因。

谢谢:)

1 个答案:

答案 0 :(得分:2)

这是ref问题的副本 - 所有你的词典 - "值"对相同数据保持相同的引用 - 只要使用一个引用来更新数据,就可以修改所有引用的基础数据。如果你想要有不同的和不同的列表,你需要copy.deepcopy()当你把它放入你的词典。

您可以在pyton对象上使用id()获取唯一ID,以区分/比较它们是否相同"相同"或者"不同的"像这样:

def pp (l, s):
    """silly pretty printer"""
    print(s+"\n")
    print("    ",id(l), l)
    for n in l:
        print("        ", id(n),n) 
        if n is type(list):
            for m in n:
                print("            ",id(m),m)
    print()


data         = [ [3,4] , "aa" ]              # a list, mutable
dataWithData = [ data, data, [99,100], 1]    # contains 2 refs to data, 1 new list 
                                             # if you append to dataWithData[1] both change

pp(dataWithData, "original list [ data, data, [99,100], 1]" )

dataWithData2 = dataWithData[:]  # shallow copy

pp(dataWithData2, "shallow copy of [ data, data, [99,100], 1]" ) 

import copy
dataWithData3 = copy.deepcopy( dataWithData)
pp(dataWithData3, "deepcopyed [ data, data, [99,100], 1]")

原始列表[ data, data, [99,100], 1]

 764500835912 [[[3, 4], 'aa'], [[3, 4], 'aa'], [99, 100], 1]
     764497577480 [[3, 4], 'aa']
     764497577480 [[3, 4], 'aa']
     764500834824 [99, 100]
     1763008736 1

[ data, data, [99,100], 1]

的浅层副本
 # only the ref to the outer varname was changed - it is a new name but points
 # to all the old data 
 764500834888 [[[3, 4], 'aa'], [[3, 4], 'aa'], [99, 100], 1]
     764497577480 [[3, 4], 'aa'] # same
     764497577480 [[3, 4], 'aa'] # same
     764500834824 [99, 100]      # same
     1763008736 1                # same

deepcopyed [ data, data, [99,100], 1]

 # all were changed, so all point to "new" data
 764500835400 [[[3, 4], 'aa'], [[3, 4], 'aa'], [99, 100], 1]
     764500834952 [[3, 4], 'aa']
     764500834952 [[3, 4], 'aa']
     764498168136 [99, 100]
     1763008736 1

复制&粘贴到您的编辑器中并进行游戏 - 更改内容和pp各种版本以查看结果(或检查ID)。