Vyacheslav
Vyacheslav

Reputation: 662

All dictionaries in a list change their values when the dictionary changes

Please help me to resolve the issue.

I create a list. Then I append to it dictionaries. I have 2 the same dictionary in the list after the second dictionary appending and 3 the same dictionary in the list after the third dictionary appending.

*** Settings ***
Library  Collections

*** Variables ***
&{test_dictionary}
@{positions_list}

*** Test Cases ***
Compaund list
    set to dictionary  ${test_dictionary}  Name=First Name  Length=50  db_name=f_name
    Append the dictionary to the list
    set to dictionary  ${test_dictionary}  Name=Last Name  Length=60  db_name=l_name
    Append the dictionary to the list
    set to dictionary  ${test_dictionary}  Name=Email Address  Length=40  db_name=email
    Append the dictionary to the list

*** Keywords ***
Append the dictionary to the list
    log dictionary  ${test_dictionary}
    append to list  ${positions_list}  ${test_dictionary}
    log list  ${positions_list}

So, I have the strange list after the test:

List length is 3 and it contains following items:
0: {'Name': 'Email Address', 'Length': '40', 'db_name': 'email'}
1: {'Name': 'Email Address', 'Length': '40', 'db_name': 'email'}
2: {'Name': 'Email Address', 'Length': '40', 'db_name': 'email'}

Why are first and second dictionaries replaced?

Upvotes: 3

Views: 904

Answers (1)

Todor Minakov
Todor Minakov

Reputation: 20067

Because in python a variable is (roughly put) a pointer to a memory location; and a dictionary is a mutable object - e.g. you can change the value in that memory location.

When you append it to the list, what happens is the list element becomes "this object, that points to that memory address" - not " the dump of that object, as new memory location", which you might think. Then you change the dictionary's value - e.g. the value in the memory address. And doing so, it is also changed for the list member - it still points to the same memory address, which now holds a different value.

If you want the list to have 3 different dictionaries in the list - use 3 variables.

Alternatively, if you don't want that, store in the list a copy of the dictionary; being a copy, it won't change if the original does:

*** Settings ***
Library  Collections

*** Variables ***
&{test_dictionary}
@{positions_list}

*** Test Cases ***
Compaund list
    set to dictionary  ${test_dictionary}  Name=First Name  Length=50  db_name=f_name
    Append the dictionary to the list
    set to dictionary  ${test_dictionary}  Name=Last Name  Length=60  db_name=l_name
    Append the dictionary to the list
    set to dictionary  ${test_dictionary}  Name=Email Address  Length=40  db_name=email
    Append the dictionary to the list

*** Keywords ***
Append the dictionary to the list
    &{dict_copy}=    Copy Dictionary    ${test_dictionary}
    log dictionary  ${dict_copy}
    append to list  ${positions_list}  ${dict_copy}
    log list  ${positions_list}

Upvotes: 4

Related Questions