2016-02-23 4 views
0

Почему это происходит? Должен ли я использовать копию numpy.array? но , похоже, работает с 1-м кодом. Не могу понять, почему.Почему list.append ведет себя по-разному в цикле «for» с разными уровнями

import numpy as np 

n=3 
h_all=[] 
h=np.zeros((n,n)) 

for i in range(0, n): 
    h = h + 1. 
    h_all.append(h)   
print h_all 

дает

[array([[ 1., 1., 1.], 
[ 1., 1., 1.], 
[ 1., 1., 1.]]), array([[ 2., 2., 2.], 
[ 2., 2., 2.], 
[ 2., 2., 2.]]), array([[ 3., 3., 3.], 
[ 3., 3., 3.], 
[ 3., 3., 3.]])] 

который хорош , но если я код, как

n=3 
h_all=[] 
h=np.zeros((n,n)) 
maxnum=3 

for k in range(0, n): 
    for i in range(0, n): 
     for j in range(0, n): 
      h[i,j] = h[i,j] + 1. 
    h_all.append(h[:])   
print h_all 
It becomes: 
[array([[ 3., 3., 3.], 
[ 3., 3., 3.], 
[ 3., 3., 3.]]), array([[ 3., 3., 3.], 
[ 3., 3., 3.], 
[ 3., 3., 3.]]), array([[ 3., 3., 3.], 
[ 3., 3., 3.], 
[ 3., 3., 3.]])] 

ответ

0
for k in range(0, n): 
    .... 
    h_all.append(h[:]) 

помещает указатель на h в список h_all. Поскольку вы изменяете h на каждом шаге на месте, тот же указатель помещается в h_all каждый раз. В конце h_all отображает текущее значение h в каждом слоте.

Это распространенная проблема при работе с списками и словарями Python. Вы должны добавить копию на каждом шаге на итерации, а не на изменяемый объект.

Чтобы уточнить это, ознакомьтесь с id(h_all[0]) и id(h_all[1]); Я ожидаю, что они будут такими же. Или попробуйте h +=1 после цикла, и посмотрите значения h_all изменить.

Я должен добавить, что h[:] создает копию, если h - это список, но нет, если это массив.

+0

Спасибо за помощь @hpaulj. Ниже приведено следующее: ** 1 ** 'id (h_all [0])' и 'id (h_all [i])' не совпадают (для обоих кодов) ** 2 ** ' h + = 1' изменяет все 'h' в' h_all' для второго кода, но не влияет на результат 'h_all' от первого кода. ** 3 ** В первом коде, почему h не действует как указатель так же, как во втором коде? – Gang

+0

Я забыл; 'h [:]' создает 'view' массива. Это новый объект, но он разделяет базовые данные. Таким образом, 'id' будет отличаться на каждой итерации; но значения разделяются. 'h.copy()' необходимо использовать в итерации следующим образом. – hpaulj

+0

'h.copy()' работал! Благодаря! – Gang

Смежные вопросы