哪个类应该存储查找表? [英] Which class should store the lookup table?
问题描述
世界包含位于不同位置的特工,而在任何位置只有一个特工.每个代理商都知道他在哪里,但我还需要快速检查在给定位置是否有代理商.因此,我还要维护一张从位置到代理商的地图.我在确定此映射属于哪个位置时遇到问题:class World
,class Agent
(作为类属性)或其他位置.
The world contains agents at different locations, with only a single agent at any location. Each agent knows where he's at, but I also need to quickly check if there's an agent at a given location. Hence, I also maintain a map from locations to agents. I have a problem deciding where this map belongs to: class World
, class Agent
(as a class attribute) or elsewhere.
在下面,我将查找表agent_locations
放在class World
中.但是现在,座席必须在每次移动时都呼叫world.update_agent_location
.这很烦人.如果我以后决定跟踪有关代理的其他信息(除了它们的位置之外)怎么办?我需要在整个Agent
代码中将调用添加回世界对象吗?
In the following I put the lookup table, agent_locations
, in class World
. But now agents have to call world.update_agent_location
every time they move. This is very annoying; what if I decide later to track other things about the agents, apart from their locations - would I need to add calls back to the world object all across the Agent
code?
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
对象,则查找表将需要特定于世界.
I can instead put agent_locations
in class Agent
as a class attribute. But that only works when I have a single World
object. If I later decide to instantiate multiple World
objects, the lookup tables would need to be world-specific.
我相信有更好的解决方案...
I am sure there's a better solution...
我在代码中添加了几行以显示agent_locations
的用法.请注意,它仅在Agent
对象内部使用,但我不知道这种情况是否会永远存在.
I added a few lines to the code to show how agent_locations
is used. Note that it's only used from inside Agent
objects, but I don't know if that would remain the case forever.
推荐答案
与OOP一起使用 is 和 has 来谈论对象是有帮助的. World
具有Agents
的列表和Locations
的列表. Location
有一个 Agent
. Agent
有一个 Location
和一个World
.
It helps with OOP to talk about the objects in terms of is a and has a. A World
has a list of Agents
and a list of Locations
. A Location
has an Agent
. An Agent
has a Location
and a 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
进行脑力劳动,向Location
添加新属性,例如terrain,很容易看到这种封装的好处.同样,向Agent
添加新事物(例如武器),仅需要类似于move()
的特定于武器的功能.请注意,World
根本不需要参与move()
.严格在Agent
和Location
之间进行移动.
Go through the mental exercise of adding a new attribute to a Location
, such as terrain, and it's easy to see the benefits of such encapsulation. Likewise, adding new things to Agent
, such as a weapon, just requires a weapon-specific function similar to move()
. Note that the World
doesn't need to get involved in the move()
at all. The move is handled strictly between the Agent
and the Location
.
这篇关于哪个类应该存储查找表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!