用户自定义类型作为字典键
这几天我一直在琢磨哈希表和字典的概念,但一直找不到合适的解决办法。希望你们能原谅我这个初学者(可能也是重复的问题),并抽时间回答我。
在我初始化“世界”(这是解决经典的GridWorld MDP问题的一部分,但这不是重点)时,我创建了多个State
的实例,每个实例都有一个独特的、能代表它的元组(row, column)
。我的问题是,如何存储和引用这些实例。
更具体一点...
我用以下代码创建了几个状态(在尝试了字典、集合和NumPy数组等多种方法失败后,最终选择用列表来存储它们):
(rows, columns) = (3, 4)
s = [[] for _ in range(rows)]
for r in range(rows):
for c in range(columns):
s[r].append(State(r, c))
这个类的定义是:
class State:
def __init__(self, row, col):
self.row = row
self.col = col
def __hash__(self):
return hash((self.row, self.col))
def __eq__(self, other):
return (self.row == other.row) & (self.col == other.col)
# __hash__ and __eq__ are here because I know they should,
# though I currently don't know how to use them.
# I believe that is actually the real question here...
在我的代码后面,我想给每个状态分配一个属性neighbours
,这个属性是一个列表,里面包含了在网格上与它实际相邻的状态。这里的“实际”是指这些状态不是状态的副本或某种表示,而是真正的状态本身。下面是我实现的代码,但并不是我想要的结果:
def add_neighbours(self):
if self.row == 0:
if self.col == 0:
self.neighbours = [(0, 1), (1, 0)]
elif self.col == 1:
self.neighbours = [(0, 0), (0, 2)]
elif self.col == 2:
self.neighbours = [(0, 1), (1, 2), (0, 3)]
elif self.col == 3:
self.neighbours = [(0, 2), (1, 3)]
elif self.row == 1:
if self.col == 0:
self.neighbours = [(0, 0), (2, 0)]
elif self.col == 1:
self.neighbours = [] # Pit, N/A
elif self.col == 2:
self.neighbours = [(0, 2), (1, 3), (2, 2)]
elif self.col == 3:
self.neighbours = [(0, 3), (1, 2), (2, 3)]
elif self.row == 2:
if self.col == 0:
self.neighbours = [(1, 0), (2, 1)]
elif self.col == 1:
self.neighbours = [(2, 0), (2, 2)]
elif self.col == 2:
self.neighbours = [(2, 1), (1, 2), (2, 3)]
elif self.col == 3:
self.neighbours = [(2, 2), (1, 3)]
这个neighbours
的定义让我可以从s
中调用相关的状态,但看起来并不美观,肯定也不优雅。我想要的是类似这样的东西:
def add_neighbours(self):
if self.row == 0:
if self.col == 0:
self.neighbours = [State((0, 1)), State((1, 0))]
elif self.col == 1:
self.neighbours = [State((0, 0)), State((0, 2))]
elif self.col == 2:
self.neighbours = [State((0, 1)), State((1, 2)), State((0, 3))]
etc...
其中State((r, c))
是被反复调用的实际状态(或者我应该说是状态的引用)。
任何评论都将非常感谢。谢谢。
注意:我知道有一些详细的解释尝试(例如这个Stack Overflow的问题和这个Python Wiki的参考),但不幸的是,我没能理解它们,只好请求更多的解释。
1 个回答
0
这是一个平面图,每个节点可以用一个矩阵来定位和索引。
你可以做的事情有:
- 创建一个索引结构,用来存储每个单独的单元格,这样你就可以通过坐标来引用一个单元格。
- 创建每个空的单独单元格,并把它们存储在这个索引结构中。
- 一旦每个空单元格创建完成,就把每个单元格和它的邻居连接起来。
你需要先把每个状态创建为空,因为你不能引用一个还没创建的对象。
代码示例:
# 1. Backing index
table = {}
# 2. Each State is empty.
table[(0, 0)] = State(0, 0)
table[(0, 1)] = State(0, 1)
table[(1, 0)] = State(1, 0)
table[(1, 1)] = State(1, 1)
# ...
# 3. Initialize each State.
table[(0, 0)].initialize()
table[(0, 1)].initialize()
# ...
class State:
def initialize(self):
if ...:
# self.neighbours is a list of States.
self.neighbours = [table[(x, y)], table[(a, b)], table[(p, q)]]