2016-05-31 5 views
0

Я хочу взять данные от пользователя и инициализировать список словарей. У меня есть следующий блок, который отлично работает.Инициализация списка словарей

people = [] 

for p in range(3): 
    cell = {"name": "","age" : 0, "education" : "","height" : 0} 
    cell["name"] = input("name:") 
    cell["age"] = int(input("age:")) 
    cell["education"] = input("education:") 
    cell["height"] = float(input("height:")) 
    people.append(cell) 

Проблема у меня есть, почему следующий блок не работает для меня.

people = [] 

cell = {"name": "","age" : 0, "education" : "","height" : 0} 
for p in range(0,3): 
    cell["name"] = input("name:") 
    cell["age"] = int(input("age:")) 
    cell["education"] = input("education:") 
    cell["height"] = float(input("height:")) 
    people.append(cell) 

Я не понимаю, почему в конце итерации У меня есть список инициализирован с последним входом все 3 раза, я имею в виду, когда я использую эту строку:

cell["name"] = input("name:") 

не должен предыдущее значение было заменено новым?

+0

Вы все модификации и тот же объект 'cell' и добавляет его в' списке people'. –

+1

О тесно связанной заметке: http: // stackoverflow.com/questions/240178/python-list-of-lists-changes-reflection-through-sublists-неожиданно –

ответ

3

Важной частью является эта строка:

cell = {"name": "","age" : 0, "education" : "","height" : 0} 

здесь создать словарь и сохранить ссылку на него под cell

Если вы сделаете это до цикла (как в вашем втором примере), вы создали только один словарь и добавили его в список три раза. Поэтому, если вы меняете что-либо внутри какого-либо словаря, ваши изменения будут отображаться во всех индексах списка (поскольку все они указывают на один и тот же словарь)

Однако, если вы запустите линию внутри своего цикла, вы фактически создаете три разных словарей, которые по сути вы хотите здесь. Вот почему ваш первый пример работает, а второй - нет.

+0

Итак, изменения, которые я создаю во время воздействия цикла, и ячейки, которые я уже добавил в список? – theVoid

+2

Да, потому что в вашем списке есть только «ссылки» на словари. Таким образом, в вашем втором коде вы 1. создаете словарь 2. меняете его значения 3. используйте ссылку на него в списке 4. измените значения одного и того же словаря снова 5. добавьте ** ту же ** ссылку на тот же словарь в список ... – Keiwan

1

В этом разница между передачей по значению и передачей по ссылке. Передача по ссылке или указатель на других языках означает, что переменная указывает на пятно в памяти. В Python словари ведут себя таким образом, а это значит, что, поскольку во второй версии вы меняете то, что существует в словаре, а затем добавляете его, то, что вы на самом деле делаете, это добавить словарь SAME к массиву вторым (и третьим) временем , Между каждым из этих времен происходит изменение его значений, но когда вы смотрите на массив в конце, ТОЛЬКО обновленный словарь появляется три раза.

В первом примере вы создаете новую копию переменной cell для каждого цикла, что приводит к другой ячейке памяти. Это в основном РАЗЛИЧНЫЙ словарь каждый раз, который в этом случае дает вам результат, который вы ищете.

+2

В python на самом деле нет понятия «передача по значению» или «передача по ссылке». В python все «передается по ссылке». – syntonym

1

не должно быть стерто предыдущее значение, а новое - для его места?

Нет! Это связано с тем, что каждый цикл изменяет тот же объект, поскольку ссылка не изменяется. Вот почему вы показываете последние значения итераций три раза.

Try:

for p in range(0,3): 
    cell = {"name": "","age" : 0, "education" : "","height" : 0} 
    cell["name"] = input("name:") 
    cell["age"] = int(input("age:")) 
    cell["education"] = input("education:") 
    cell["height"] = float(input("height:")) 
    people.append(cell) 
+0

Вы можете изменить определение 'cell' на' cell = {} '. –