【发布时间】:2011-01-20 23:12:30
【问题描述】:
我正在使用下面的类来创建一个表,我需要找到一种方法,不仅使它更快,而且与它的交互更快:
class Table(object):
"""a three dimensional table object"""
def __init__(self, xsize=1, ysize=1, zsize=1):
self.xsize = xsize
self.ysize = ysize
self.zsize = zsize
self.data = [0] * (xsize * ysize * zsize)
def __getitem__(self, key):
x, y, z = self.__extractIndices(key)
return self.data[x + self.xsize * (y + self.ysize * z)]
def __setitem__(self, key, value):
x, y, z = self.__extractIndices(key)
self.data[x + self.xsize * (y + self.ysize * z)] = value
def __extractIndices(self, key):
x = y = z = 0
if (self.ysize > 1):
if (self.zsize > 1):
if len(key) != 3:
raise IndexError
else:
x, y, z = key
elif len(key) != 2:
raise IndexError
else:
x, y = key
elif not isinstance(key, int):
raise IndexError
else:
x = key
return (x, y, z)
def resize(self, xsize=1, ysize=1, zsize=1):
"""resize the table preserving data"""
oldlist = list(self.data)
self.data = [0] * (xsize * ysize * zsize)
self.xsize = xsize
self.ysize = ysize
self.zsize = zsize
for i in range(0, oldlist):
self.data[1] = oldlist[i]
在这一点上,我需要确定两个列表中的数据是否等同于每个 z
所以我这样做了。 self.data 和 self.map.data 是上面的表类实例
for x in range(self.map.width - 1):
for y in range(self.map.height - 1):
tempflag = False
#layer 1
if self.data[x, y, 0] != self.map.data[x, y, 0]:
tempflag = True
layer1flag = True
#layer 2
if self.data[x, y, 1] != self.map.data[x, y, 1]:
tempflag = True
layer2flag = True
#layer 3
if self.data[x, y, 2] != self.map.data[x, y, 2]:
tempflag = True
layer3flag = True
#copy the data if it changed
if tempflag:
self.data = copy.deepcopy(self.map.data)
previewflag = True
显然,这是我可以想象的最慢的方法,并且考虑到我正在比较的其中一些表的大小为 200 * 200 * 3 = 120,000 个条目。我需要尽可能快。
我考虑过重写上面的比较,以像这样对一个 z 的所有条目进行切片
tempflag = False
#layer 1
slicepoint1 = 0
slicepoint2 = self.data.xsize * self.data.ysize * 1
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer1flag = True
#layer 2
slicepoint1 = self.data.xsize * self.data.ysize * 1
slicepoint2 = self.data.xsize * self.data.ysize * 2
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer2flag = True
#layer 3
slicepoint1 = self.data.xsize * self.data.ysize * 2
slicepoint2 = self.data.xsize * self.data.ysize * 3
data1 = self.data.data[slicepoint1:slicepoint2]
data2 = self.map.data.data[slicepoint1:slicepoint2]
if data1 != data2:
tempflag = True
layer3flag = True
#copy the data if it changed
if tempflag:
self.data = copy.deepcopy(self.map.data)
previewflag = True
虽然这看起来会更快,但它似乎仍然可以显着改善。例如不能使用 numpy 在 Table 类中构建数据列表吗?
我需要这个类和这个检查尽可能快地运行
如果使用 numpy 可以让我非常快速地遍历表,这样我就可以使用其中的数据进行 blit 操作来构建 tilemap,这也很好
我确实需要保留表格类的通用接口,特别是表格数据存储在self.data中的事实
总结 使用numpy可以提高运算速度吗?如果可以,我该怎么做?
【问题讨论】:
-
这看起来是一种非常缓慢且笨拙的 3D 数据存储方式。即使在 Python 中使用嵌套列表也可能更快更简单,但 numpy 数组可能是更好的答案。