【问题标题】:Python is overwriting my listPython 正在覆盖我的列表
【发布时间】:2014-01-01 19:16:18
【问题描述】:

我最近正在尝试使用 Python。我已经建立了一个 4 维数组;前三个维度定义了世界空间中的一个位置,第四个维度指的是可能属于该空间的节点。节点是我制作的预定义类。 起初列表中的每个条目都设置为无,后来我根据需要添加值。我的问题是,每当我添加这些值时,它似乎都会覆盖每个条目以等于最后一个包含的条目。 以下是调用模块的相关摘录:

import Node
myList = [[] for i in range(4)]
xDim = yDim = zDim = 0
def main():
   return 1

def setDimensions(x, y, z):
   global myList, xDim, yDim, zDim
   xDim = x
   yDim = y
   zDim = z
   myList = [ [ [ [ None for i in range(12)] for j in range(z) ] for k in range(y) ] for l in range(x) ]

def process(x, y, z, data):
   global myList
   for i in range(12):
       a = int(data[i])
       if a != 0:
           myList[x][y][z][i] = Node.Node()
           myList[x][y][z][i].setType(a, i, x, y, z)   
   print(myList[0][0][0][3].getX(), myList[0][0][0][3].getY(), myList[0][0][0][3].getZ()) 

这里是 Node 类的摘录,包含在模块 Node.py 中:

Type = xCoord = yCoord = zCoord = 0
class Node():
def main():
    return 1
def getX(self):
    global xCoord
    return xCoord

def getY(self):
    global yCoord
    return yCoord

def getZ(self):
    global zCoord
    return zCoord    

def setType(self, color, i, x, y, z):
    global xCoord, yCoord, zCoord
    xCoord = x
    yCoord = y
    zCoord = z

当我在处理方法结束时运行 print 时,我希望每次都能看到 0、0、0。相反,我看到了:

0 0 0

0 0 1

0 0 2

.

.

.

3 3 3

进一步的测试已经证实,每次我创建一个新节点并将其添加到我的列表中时,它似乎不仅占据了我想要的列表中的位置,而且还用它自己覆盖了之前的每个列表条目。我错过了什么?

【问题讨论】:

  • 你的节点不同,但它们getX返回相同的全局变量,所以你得到你的结果
  • 附带说明,除非您专门这样做是为了了解多维列表,否则您应该强烈考虑使用NumPy。 (即使您正在这样做是为了了解多维列表,您也可能想尝试构建一些类似于 NumPy 4D 数组的东西,作为您的第一个学习练习之一……)
  • 欢迎来到 SO!请注意,数组和列表是两个完全不同的概念,它们看起来很相似。如果您想要真正的数组,请考虑 abamerts 建议。
  • 谢谢你们三个。我以前听说过 NumPy。不过,我想我真的应该仔细看看。在 abarnet 的解决方案之后,我现在一切正常。再次感谢!

标签: python list overwrite


【解决方案1】:

问题与您的列表无关,您似乎做得正确 - 您有一大堆单独的 Node 实例。

问题在于Node 使用全局变量而不是属性,因此所有这些单独的Node 实例都会从node.getX() 返回完全相同的内容——全局变量xCoord 的值。

解决办法就是不要那样做:

class Node():
    def __init__(self):
        self.xCoord, self.yCoord, self.zCoord = 0, 0, 0
    def main():
        return 1
    def getX(self):
        return self.xCoord

    def getY(self):
        return self.yCoord

    def getZ(self):
        return self.zCoord    

    def setType(self, color, i, x, y, z):
        self.xCoord = x
        self.yCoord = y
        self.zCoord = z

然而,值得注意的是,在 Python 中几乎没有充分的理由使用这种“getter 和 setter”方法。只需编写访问node.xCoord 而不是node.getX() 的代码,就可以完全消除这些方法。

【讨论】:

  • 啊,太棒了,这把事情搞定了。正如您可能想象的那样,这在特定问题之外非常有用。显然,这是一个关键概念。所以全局变量适用于整个包,自变量覆盖整个类。其他任何东西都只会存在于它的方法中。如果我想使用全局或类范围的变量,我应该在方法的开头声明这些变量是全局的,或者明确地将它们称为 self.variableName。那个声音差不多吧?这确实解释了我在代码的其他地方遇到的很多事情。
  • @user1693804:差不多。 self 变量适用于类的每个实例,而不是类本身,它是关键。 (有类变量,但你很少需要它们。)否则,完全正确:global 变量(以及 Python 3 中的 nonlocal 闭包变量)您在引用的方法、类和实例变量的顶部声明使用类名或self,其他一切都是本地的。通常你只需要实例和局部变量。
猜你喜欢
  • 2012-11-09
  • 2012-11-03
  • 1970-01-01
  • 2019-11-14
  • 2010-11-13
  • 2019-05-09
  • 2022-01-18
  • 2021-09-01
  • 2011-06-02
相关资源
最近更新 更多