我正在建模围绕自身缠绕的正方形网格上发生的某些事情(即,如果您走过最高点,则最终到达最低点,就像圆柱一样;如果走到右边,则只是碰到了边界).我需要跟踪各种代理的位置,不同点上的资源量,并根据某些规则计算代理将要移动的方向.
对此建模的最佳方法是什么?
我是否应该制作一个表示点的类,该类具有在每个方向上返回相邻点的方法?如果是这样,我可能需要使其成为可散列的,以便可以将其用作包含完整网格的字典的键(我假设这样的网格应该是字典?)
还是我应该制作一个描述整个网格并且不将单个点显示为独立对象的类?
还是应该只使用常规(x,y)元组,并在其他地方使用允许查找邻居的方法?
我需要建模的许多内容尚未明确定义.此外,我预计表面的几何形状可能会在一天内发生变化(例如,它可能会在两个方向上相互缠绕).
编辑:另外一个问题:我应该将有关资源数量的信息附加到每个Point实例中吗?还是应该有一个单独的类,其中包含一个由Point索引的资源映射?
解决方法:
如果您想要一个不需要太多工作的可散列的Point类,请对元组进行子类化并添加自己的邻居方法.
class Point(tuple):
def r_neighbor(self):
return Point((self[0] + 1, self[1]))
def l_neighbor(self):
[...]
x = Point((10, 11))
print x
print x.r_neighbor()
元组构造函数需要一个可迭代的对象,因此需要Point((10,11));中的双括号.如果要避免这种情况,可以始终重写__new__(重写__init__是没有意义的,因为元组是不可变的):
def __new__(self, x, y):
return super(Point, self).__new__(self, (x, y))
这也可能是应用模块化算术的地方-尽管这实际上取决于您在做什么:
def __new__(self, x, y, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize, y % gridsize))
或启用任意尺寸网格,然后返回在__new__中使用元组:
def __new__(self, tup, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize for x in tup))
关于您的资源问题:由于Point是一个不可变的类,因此存储有关可能更改的资源的信息的位置很糟糕. defaultdict很方便;您不必初始化它.
from collections import defaultdict
grid = defaultdict(list)
p = Point((10, 13))
grid[(10, 13)] = [2, 3, 4]
print grid[p] # prints [2, 3, 4]
print grid[p.r_neighbor] # no KeyError; prints []
如果需要更大的灵活性,可以在默认字典中使用字典而不是列表.但是defaultdict(defaultdict)将不起作用;您必须创建一个新的defaultdict工厂函数.
def intdict():
return defaultdict(int)
grid = defaultdict(intdict)
或更简洁
grid = defaultdict(lambda: defaultdict(int))
然后
p = Point((10, 13))
grid[(10, 13)]["coins"] = 50
print grid[p]["coins"] # prints 50
print grid[p.r_neighbor]["coins"] # prints 0; again, no KeyError