Python 哪个类应该存储查找表?
世界上有不同位置的代理,任何位置都只有一个代理。每个特工都知道他在哪里,但我还需要快速检查给定地点是否有特工。因此,我还维护了从位置到代理的地图。我在确定此映射所属的位置时遇到问题:Python 哪个类应该存储查找表?,python,oop,Python,Oop,世界上有不同位置的代理,任何位置都只有一个代理。每个特工都知道他在哪里,但我还需要快速检查给定地点是否有特工。因此,我还维护了从位置到代理的地图。我在确定此映射所属的位置时遇到问题:类世界、类代理(作为类属性)或其他位置 在下面的部分中,我将查找表agent\u locations放在class-World中。但现在代理必须调用world.update\u agent\u location。这很烦人,;如果我以后决定跟踪关于代理的其他事情,除了它们的位置,我是否需要在代理代码中添加对world对
类世界
、类代理
(作为类属性)或其他位置
在下面的部分中,我将查找表agent\u locations
放在class-World
中。但现在代理必须调用world.update\u agent\u location
。这很烦人,;如果我以后决定跟踪关于代理的其他事情,除了它们的位置,我是否需要在代理
代码中添加对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\u locations
作为class属性放在class-agent
中。但只有当我有一个World
对象时,这才有效。如果我以后决定实例化多个World
对象,那么查找表需要是特定于世界的
我相信有更好的解决办法
编辑:我在代码中添加了几行,以显示如何使用
agent\u locations
。请注意,它只在代理
对象内部使用,但我不知道这种情况是否会一直持续下去。对不起,我不理解这个问题。“当代理决定移动到哪里时,他会检查以确保不会遇到其他代理”。显然,一个位置可以有0或1个代理。当然Location类有一个agent属性
locn = self.where_to_move()
if locn.agent is None:
self.move(locn)
elif locn.agent is self:
raise ConfusedAgentError()
else:
self.execute_plan_B()
好的,我想我可以提供我的答案,这可能更像是一种观点,而不是一个明确的“做这个”(我没有任何编程方面的正式培训) 我认为您
代理位置
应该是每个世界
实例的成员。
我主要从界面的角度来思考。在我看来,世界级应该负责管理你们世界的资源,在这种情况下是空间。由于World
是空间的管理者,代理应该询问他们的世界空间是否可用(即未占用),而不是彼此。因此,我认为您的self.location\u很好
更合适的调用是self.world.is\u location\u可用(x,y)
[1]
这使得世界自然要负责查找给定空间的可用性。世界级还可能有其他变量决定空间是否可用。如果那里有灌木丛呢?或者别的什么。您可能已经为每个世界的(x,y)
坐标准备了某种表格。“被占用”可能是这些对象的属性
此外:您的世界已经知道每个代理的状态(通过self.agents中代理的[(agent.x,agent.y)]
[2])。agent\u locations
dict本质上是这些属性的索引或缓存,因此属于World
class Agent:
def __init__(self, world):
self.location = None
self.world = world
def move(self, new_location):
if self.location is not None:
self.location.agent = None
new_location.agent = self
self.location = new_location
def update(self):
for new_location in self.world.locations:
if self.location_is_good(new_location):
self.move(new_location)
def location_is_good(self, location):
if location.agent is not None:
return False
class Location:
def __init__(self, x, y):
self.x = x
self.y = y
self.agent = None
关于将国家送回世界的痛苦
。。。好吧,你不可能通过让Agent
来解决这个问题。但是做update\u agent\u location(self,agent,x,y)
是完全多余的,因为x==agent.x;y==agent.y
(如果将调用它的行颠倒过来)。您只需在World中使用一种方法,update\u agent\u state(self,agent)
,World就可以使用它来更新索引。您甚至可以提交一个额外的参数来描述状态更改的类型(如果您不想每次更新所有属性)
诸如此类(请看我的脚注)
[1] 当然,除非一个位置的“优点”取决于其他变量,而不是空间是自由的。例如,如果你只应该移动到(x,y),如果1)位置可用,2)代理有1000美元支付车票,那么你应该有一个代理。你可以移动到(x,y)
,这反过来调用世界的方法,并检查它的钱包
[2] 我假设你的
self.agents={}
是一个打字错误,因为你不能append
在dict上。你是说一个列表([]
)对吗 用is a和has a来谈论对象有助于OOP。World
有一个代理列表
和一个位置列表
。位置
有一个代理
。代理
有一个位置
和一个世界
class Agent:
def __init__(self, world):
self.location = None
self.world = world
def move(self, new_location):
if self.location is not None:
self.location.agent = None
new_location.agent = self
self.location = new_location
def update(self):
for new_location in self.world.locations:
if self.location_is_good(new_location):
self.move(new_location)
def location_is_good(self, location):
if location.agent is not None:
return False
class Location:
def __init__(self, x, y):
self.x = x
self.y = y
self.agent = None
通过将新属性添加到
位置
(如地形)的心理练习,很容易看到这种封装的好处。同样,向代理添加新的东西,例如武器,只需要类似于move()
的特定于武器的功能。请注意,World
根本不需要参与move()
。在代理
和位置
之间严格处理移动,您不需要更新代理。代理位置
吗?您的快速检查必须有多快?你们有多少特工?如果你没有那么多(相对的),你可以迭代一个世界的代理,检查他们的位置。当代理决定移动到哪里时,他会检查以确保不会遇到其他代理。如果我迭代所有代理来检查这一点,我将在任何代理移动时查找每个代理的位置(执行n_-agents
操作)。更新查找表时,每个移动只需要一次操作。但是,您提供的代码没有检查这一点<代码>更新\u代理\u位置
只是覆盖在(x,y)
之前的任何人。。。无论如何,将查找表移动到代理
类真的能解决问题吗?您是否仍然需要调用代理。更新\u Agent\u位置
?让我添加一个示例代码来演示如何使用它。我只是没有把它包括在内