我有一个名为hab
的列表列表,作为2D数组。在这个列表列表中,我存储了一个名为loc
的类的元素,这就是为什么我没有使用numpy数组(它不存储数字)。
我希望通过循环遍历每个元素,用随机选择的'loc'填充每个元素。然而,似乎每当我到达行的末尾时,程序将获取最后一行元素并将其放入该行中的所有其他元素中。这意味着我最终得到的列表如下:
3 3 3 3 3
1 1 1 1 1
2 2 2 2 2
2 2 2 2 2
4 4 4 4 4
实际上我希望所有这些数字都是随机的(这是打印出每个loc
的特定特征,这就是为什么它是数字)。
以下是相关的代码:
allspec=[] # a list of species
for i in range(0,initialspec):
allspec.append(species(i)) # make a new species with new index
print 'index is',allspec[i].ind, 'pref is', allspec[i].pref
hab=[[0]*xaxis]*yaxis
respect = randint(0,len(allspec)-1)
for j in range(0,yaxis):
for k in range (0,xaxis):
respect=randint(0,len(allspec)-1)
print 'new species added at ',k,j,' is ', allspec[respect].ind
hab[k][j]=loc(k,j,random.random(),allspec[respect])
print 'to confirm, this is ', hab[k][j].spec.ind
for k in range (0,xaxis):
print hab[k][j].spec.ind
printgrid(hab,xaxis,yaxis)
print 'element at 1,1', hab[1][1].spec.ind
在循环中,我确认我创建的元素是我希望它与行print 'to confirm, this is ', hab[k][j].spec.ind
一起使用,此时它很好。只有当退出该循环时,它才会以某种方式填充行上的每个元素。我不明白!
答案 0 :(得分:8)
问题在于:
hab=[[0]*xaxis]*yaxis
由于上述声明,hab
由yaxis
引用组成同一列表:
In [6]: map(id, hab)
Out[6]: [18662824, 18662824, 18662824]
修改hab[k][j]
时,所有其他hab[][j]
也会更改:
In [10]: hab
Out[10]: [[0, 0], [0, 0], [0, 0]]
In [11]: hab[0][0] = 42
In [12]: hab
Out[12]: [[42, 0], [42, 0], [42, 0]]
要修复,请使用
hab=[[0]*xaxis for _ in range(yaxis)]
现在hab
的每个条目都引用一个单独的列表:
In [8]: map(id, hab)
Out[8]: [18883528, 18882888, 18883448]
In [14]: hab
Out[14]: [[0, 0], [0, 0], [0, 0]]
In [15]: hab[0][0] = 42
In [16]: hab
Out[16]: [[42, 0], [0, 0], [0, 0]]
答案 1 :(得分:3)
另一个答案解释了什么是错的,但我希望使用您可能不知道的Python功能提供更清晰的实现。
import random
from pprint import pprint
class species(object):
def __init__(self, ind):
self.ind = ind
self.perf = ind
def makespecies(n):
# using list comprehensions, we don't need a for-loop
# we could also have said `map(species, range(n))`
return [species(i) for i in range(n)]
def makegrid(w, h, species):
# rather than initialize empty lists, we create a new list
# for each row as we go. This avoids the bug in your code
# while also being much easier to read.
return [[random.choice(species) for i in range(w)] for j in range(h)]
def printgrid(grid, attr):
pprint([[getattr(e, attr, None) for e in row] for row in grid])
speclist = makespecies(10)
grid = makegrid(5,5,speclist)
printgrid(grid, 'ind')
这将打印如下内容:
[[5, 8, 6, 8, 9],
[9, 3, 3, 1, 3],
[3, 8, 1, 5, 5],
[7, 4, 7, 1, 7],
[4, 3, 3, 1, 9]]
另请注意,如果您正在使用大型数组或对它们执行面向矩阵的操作,则应考虑使用numpy。你可以创建一个“主”嵌套数组(就像这个一样),它将你的物种对象作为原始数据,然后vectorize
使它成为数值运算的数组。