【问题标题】:elements being copied along a list in python在python中沿列表复制元素
【发布时间】:2012-11-27 23:05:25
【问题描述】:

我有一个名为hab 的列表列表,充当二维数组。在这个列表列表中,我存储了一个名为 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 相同的元素,此时它很好。只有当该循环退出时,它才会以某种方式用相同的东西填充行上的每个元素。我不明白!

【问题讨论】:

  • 你应该在这里使用random.choice,或者甚至可能使用random.sample
  • 你能展示你的printgrid函数吗?很有可能您实际上创建了正确的列表,但随后打印错误。

标签: python list class


【解决方案1】:

问题出在这里:

hab=[[0]*xaxis]*yaxis

作为上述声明的结果,habyaxis 引用到同一个列表

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]]

【讨论】:

  • 谢谢!你能告诉我为什么我的定义方式行不通吗?
  • @CatherineGeorgia:请查看扩展答案。
【解决方案2】:

另一个答案解释了问题所在,但我想使用您可能不知道的 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 将其转换为 numpy 数组以进行数值运算。

【讨论】:

  • 看起来确实比我拥有的东西优雅得多,非常感谢。
猜你喜欢
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 2013-12-15
  • 2018-06-22
  • 2010-10-10
  • 2020-07-14
相关资源
最近更新 更多