python - 哪个类应该存储查找表?

标签 python oop

<分区>

世界包含不同位置的代理,任何位置都只有一个代理。每个特工都知道他在哪里,但我还需要快速检查给定位置是否有特工。因此,我还维护了一张从位置到代理的 map 。我无法确定这张 map 属于哪里:class Worldclass Agent(作为类属性)或其他地方。

在下面,我将查找表 agent_locations 放在 class World 中。但是现在代理每次移动时都必须调用 world.update_agent_location。这很烦人;如果我稍后决定跟踪关于代理的其他事情,除了他们的位置之外,我是否需要在整个 Agent 代码中添加对 world 对象的调用?

class World:
  def __init__(self, n_agents):
    # ...
    self.agents = []
    self.agent_locations = {}
    for id in range(n_agents):
      x, y = self.find_location()
      agent = Agent(self,x,y)
      self.agents.append(agent)
      self.agent_locations[x,y] = agent
  def update_agent_location(self, agent, x, y):
    del self.agent_locations[agent.x, agent.y]
    self.agent_locations[x, y] = agent
  def update(self): # next step in the simulation
    for agent in self.agents:
      agent.update() # next step for this agent
  # ...

class Agent:
  def __init__(self, world, x, y):
    self.world = world
    self.x, self.y = x, y
  def move(self, x1, y1):
    self.world.update_agent_location(self, x1, y1)
    self.x, self.y = x1, y1
  def update():
    # find a good location that is not occupied and move there
    for x, y in self.valid_locations():
      if not self.location_is_good(x, y):
        continue
      if self.world.agent_locations[x, y]: # location occupied
        continue
      self.move(x, y)

我可以将 agent_locations 作为类属性放入 class Agent 中。但这只有在我有一个 World 对象时才有效。如果我稍后决定实例化多个 World 对象,查找表将需要特定于世界。

我相信有更好的解决方案...

编辑:我在代码中添加了几行以显示如何使用 agent_locations。请注意,它仅在 Agent 对象内部使用,但我不知道这种情况是否会永远如此。

最佳答案

好吧,我想我可以提供我的答案,这可能更像是一种意见,而不是明确的“这样做”(我没有接受过任何正式的编程培训)。

我认为您 agent_locations 应该是每个 World 实例的成员。

我尝试主要从界面的角度来思考。在我看来,世界级应该负责管理你的世界的资源,在这种情况下是空间。由于 World 是空间的管理者,Agent 应该询问他们的 world 空间是否可用(即未被占用),而不是互相询问。因此,我认为您的 self.location_is_good 调用更合适的是 self.world.is_location_available(x, y) [1]

这使得世界很自然地负责查找给定空间的可用性。 World 类可能还有其他变量来决定空间是否可用。如果那里有灌木丛怎么办?或者其他的东西。您可能已经为每个世界的 (x, y) 坐标创建了某种表格。被“占用”可以是这些对象的属性。

此外:您的世界已经知道每个代理的状态(通过 [(agent.x, agent.y) for agent in self.agents] [2])。 agent_locations 字典本质上是这些属性的索引或缓​​存,因此属于 World

关于将状态发送回 World 的痛苦……好吧,您不会通过让 Agent 来解决这个问题。但是执行 update_agent_location(self, agent, x, y) 是完全多余的,因为 x == agent.x; y == agent.y (如果你反转你调用它的行)。您可以在 World 中简单地使用一种方法,update_agent_state(self, agent),World 可以使用它来更新其索引。您甚至可以提交一个额外的参数来描述状态更改的类型(如果您不想每次都更新所有属性)。

class World(object):
  # ...
  def update_agent_state(self, agent, state_change=None):
    # Update properties based on what changed, or
    # drop state_change param and update everything everytime
    if state_change == Agent.LOCATION_CHANGE:
      self.agent_locations[agent.x, agent.y] = agent
    elif state_change == Agent.WHATEVER:
      pass

class Agent(object):
  LOCATION_CHANGE = 1

  def update(self):
    for x, y in self.valid_locations():
      if not self.can_move_to(x, y)
        continue

      self.move(x, y)

  def can_move_to(self, x, y):
    """Determines if x, y is a location where we can move."""
    if not self.world.is_location_available(x, y):
      return False
    if not self.has_money_to_travel_to(x, y):
      return False

    return True

  def move(self, x, y):
    """Moves to x, y and notifies world of state change."""
    self.x = x
    self.y = y

    self.world.update_agent_state(self, Agent.LOCATION_CHANGE)

类似的东西(阅读我的脚注)。

[1] 当然,除非空间的“好”取决于其他变量,而不是空间是否空闲。例如。如果您只应在 1) 位置可用且 2) 代理商有 1000 美元支付机票时移动到 (x, y),那么您应该有一个 Agent.can_move_to(x, y) 依次调用 world 的方法,并检查其钱包。

[2] 我假设您的 self.agents = {} 是一个拼写错误,因为您不能在 dict 上append。您是说列表 ([]) 对吗?

关于python - 哪个类应该存储查找表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4880691/

相关文章:

Python Black Jack 游戏变种

python - 如何使用 Selenium 获取此索引?

python - 用于调用 TKinter GUI 的单元测试

javascript - 如何从构造函数返回单个数组项

java - 回调和 dto 之间有什么关系?

Python有趣的数组索引

python - 属性错误: 'NodeList' object has no attribute 'getElementsByTagName'

c++ - 访问组合方法

java - get 和 set 方法有什么意义

c# - 自建的Node <T>\List <T>类到系统节点和列表之间的C#模糊引用