Sounds like you are on the right track. Having a location or container keep a set or dictionary of contained entities is a perfectly valid way of organizing that sort of data. I'm a little bit concerned by the word "synced" because I have never heard that term used when describing this sort of problem. Anyway, I use what is called a publisher/subscriber model for events. Basically, entities that are interested in certain types of events will subscribe for messages about those events. When an event occurs, a publisher is instructed to publish a message about the event. Messages have a topic indicating which type of event occurred. This is how the publisher knows which entities to notify about the event.
Relating this to your type of game, say you have a room representing a shop. When a character enters or exits the shop, you could publish a message. Shopkeepers could subscribe for this message, and issue a greeting or farewell as appropriate. Let me see if I can scratch up a code example.
import collections
class Publisher(object):
def __init__(self):
self._subscriptions = collections.defaultdict(set)
def publish(self, topic, *args, **kwargs):
subscribers = self._subscriptions[topic]
for subscriber in subscribers:
subscriber(topic, *args, **kwargs)
def subscribe(self, topic, subscriber):
self._subscriptions[topic].add(subscriber)
def unsubscribe(self, topic, subscriber):
self._subscriptions[topic].discard(subscriber)
publisher = Publisher()
class Room(object):
def __init__(self):
self.entities = set()
def on_enter(self, entity):
self.entities.add(entity)
publisher.publish(('on_enter', self), entity)
def on_exit(self, entity):
publisher.publish(('on_exit', self), entity)
self.entities.discard(entity)
shop = Room()
class Character(object):
def __init__(self, name):
self.name = name
def enter(self, room):
room.on_enter(self)
def leave(self, room):
room.on_exit(self)
player = Character("bheo")
class Shopkeeper(object):
def __init__(self, name, greeting, farewell):
self.name = name
self.greeting = greeting
self.farewell = farewell
def enter(self, room):
room.on_enter(self)
publisher.subscribe(('on_enter', room), self.say_hello)
def leave(self, room):
publisher.unsubscribe(('on_exit', room), self.say_goodbye)
room.on_exit(self)
def say_hello(self, topic, entity):
print self.greeting.format(entity.name)
def say_goodbye(self, topic, entity):
print self.farewell.format(entity.name)
cleric = Shopkeeper('Cleric', 'Blessings of the Gods upon you, {0}.',
'May the Gods light your path, {0}.')
blacksmith = Shopkeeper('Blacksmith', 'Finest arms and armor, {0}.',
'Thank you for your business, {0}.')
cleric.enter(shop)
blacksmith.enter(shop)
player.enter(shop)
player.leave(shop)