python:表示包裹自身的方形网格(圆柱体)
我正在为一个包裹在自身上的正方形网格上发生的事情建模(即,如果你走到最高点,你会在最低点结束,就像一个圆柱体;如果你走到右边,你只会碰到边界)。我需要跟踪各种代理的位置、不同点的资源量,并根据某些规则计算代理将移动的方向 最好的建模方法是什么 我是否应该创建一个表示点的类,该类具有返回每个方向上相邻点的方法?如果是这样的话,我可能需要将其设置为可散列的,以便可以将其用作包含完整网格的字典的键(我假设这样的网格应该是一个字典?) 或者我应该创建一个类来描述整个网格,而不是将单个点作为独立对象公开 或者我应该只使用常规(x,y)元组,并在其他地方使用允许查找邻居的方法吗 我需要建模的很多东西还没有明确定义。此外,我预计曲面的几何图形可能有一天会发生变化(例如,它可以在两个方向上包裹自己) 编辑:另一个问题:我是否应该将资源数量的信息附加到每个点实例;或者我应该有一个单独的类,它包含按点索引的资源映射 我需要跟踪位置 在各种代理中 不同点的资源,以及 计算代理的方向 将基于某些特定的 规则 对我来说,这听起来像一张图表,尽管我试图在每个问题中看到一张图表。您提到的所有操作(移动、存储资源、查找移动位置)在图形中都非常常见。您还可以轻松地更改拓扑,从圆柱体到圆环体或以任何其他方式 唯一的问题是它比其他表示法占用更多的空间python:表示包裹自身的方形网格(圆柱体),python,oop,Python,Oop,我正在为一个包裹在自身上的正方形网格上发生的事情建模(即,如果你走到最高点,你会在最低点结束,就像一个圆柱体;如果你走到右边,你只会碰到边界)。我需要跟踪各种代理的位置、不同点的资源量,并根据某些规则计算代理将移动的方向 最好的建模方法是什么 我是否应该创建一个表示点的类,该类具有返回每个方向上相邻点的方法?如果是这样的话,我可能需要将其设置为可散列的,以便可以将其用作包含完整网格的字典的键(我假设这样的网格应该是一个字典?) 或者我应该创建一个类来描述整个网格,而不是将单个点作为独立对象公开
另一方面,您可以使用创建图形,甚至可能使用一些图形算法来计算代理的位置。如果您想要一个无需太多工作的hashable
Point
类,可以对tuple进行子类化,并添加您自己的邻居方法
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()
元组构造函数需要一个iterable,因此在点((10,11))
中使用双参数;如果要避免这种情况,可以始终重写\uuuuu new\uuuuu
(重写\uuuuuuu init\uuuuuu
是毫无意义的,因为元组是不可变的):
这可能也是应用模块化算法的地方——尽管这实际上取决于您正在做什么:
def __new__(self, x, y, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize, y % gridsize))
或者启用任意维度网格,并返回到使用\uuuu new\uuuu
中的元组:
def __new__(self, tup, gridsize=100):
return super(Point, self).__new__(self, (x % gridsize for x in tup))
关于您关于资源的问题:因为Point
是一个不可变的类,所以它不适合存储关于可能更改的资源的信息。一个默认的dict会很方便;您不必初始化它
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 []
如果您想要更大的灵活性,可以使用dict而不是defaultdict中的列表;但是defaultdict(defaultdict)
不起作用;您必须创建一个新的defaultdict工厂函数
def intdict():
return defaultdict(int)
grid = defaultdict(intdict)
或者更简洁地说
grid = defaultdict(lambda: defaultdict(int))
然后
听起来很像你会使用模数的东西,不管你如何表示地图。用
a[i%len(a)]
索引列表将产生总括。关于你的编辑,请参阅下文谢谢这是一个很好的建议。在这个特殊的例子中,我不能使用它,因为我需要视线的概念(如果我保持x,y坐标的话,定义视线要容易得多),但我会在其他情况下使用它。谢谢,这比定义\uuuuuuuu散列\uuuuu
方法要好。谢谢你关于存储额外资源的附加注释。除了它的元组
部分之外,点本身不是可变的吗?换句话说,如果我向Point添加一个新的实例变量,它不是可以完全更改而不会出现任何微妙的复杂情况吗?简单地说,因为tuple
中的子类,Point
必须是不可变的。简而言之,不可变类型在其\uuuu new\uuu
函数中设置其属性。一旦完成,它们就不能被更改,即使是通过一个子类。因此,由于Point
使用tuple的\uuuuu new\uuuuu
函数(在本例中通过super
访问)创建实例,因此结果是一个不可变的点。不变性的好处是它使散列更容易、更一致。如果点
是可变的,点
的位置可能会改变,但散列不会改变,因此点
将散列到网格
中的相同位置。作为补充,如果您想拥有一个可变的资源
类,您可以将点
作为该类的属性。甚至有办法使点
为只读,这样可用资源可以更改,但位置锁定到实例。
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