有没有办法在实例化之前引用类对象?

时间:2015-04-01 03:29:48

标签: python python-2.7

我正在尝试使用Python制作一个简单的文本游戏。我有一个Room课程:

class Room():
    def __init__(self, monster, exits, loot):
        self.room_guard = monster
        self.exits = exits
        self.guard_is_alive = True
        self.loot = loot

当我创建房间时,我收到错误,因为我在创建它们之前调用它们:

room_2 = Room(spider, {"West": room_3, "East": room_4, "South": room_1}, 2)
room_1 = Room(trogdor, {"North": room_2}, 2)

2号房间无法"South": room_1,因为它尚未实例化。有办法解决这个问题吗?

4 个答案:

答案 0 :(得分:6)

两个选项:间接,创建后的分配。

不是直接引用房间,而是使用dict将房间名称映射到房间:

rooms = {}
rooms['room_2'] = Room(spider, {"West": 'room_3', "East": 'room_4', "South": 'room_1'}, 2)
rooms['room_1'] = Room(trogdor, {"North": 'room_2'}, 2)

或者在创建Room对象后指定出口:

room_2 = Room(spider, {}, 2)
room_1 = Room(trogdor, {}, 2)

room_2.exits = {"West": room_3, "East": room_4, "South": room_1}
room_1.exits = {"North": room_2}

答案 1 :(得分:2)

在创建对象之前无法引用对象。但是,您可以在创建对象后修改exits字典,以在房间之间创建链接。一个很好的方法可能是让你创建的第二个房间通过一个额外的参数自动创建一些返回自己的链接:

class Room():
    def __init__(self, monster, exits, loot, exits_back={}):
        self.room_guard = monster
        self.exits = exits
        self.guard_is_alive = True
        self.loot = loot
        for direction, room in exits_back.items():
            room.exits[direction] = self

然后你将一个额外的字典传递给后一个房间的构造函数,让它从前一个房间将链接设置回自己:

room_2 = Room(spider, {"West": room_3, "East": room_4}, 2)        # no room_1 ref here
room_1 = Room(trogdor, {"North": room_2}, 2, {"South": room_2})   # extra dict passed

答案 2 :(得分:0)

这个问题有很多解决方案。这是另一个。此解决方案等待初始化对象,直到创建完所有对象为止。

class Room():

    def create(self, monster, exits, loot=None):
        self.room_guard = monster
        self.exits = exits
        self.guard_is_alive = True
        self.loot = loot

room_1 = Room()
room_2 = Room()
room_3 = Room()
room_4 = Room()

room_1.create('spider', {"West": room_3, "East": room_4, "South": room_1}, 2)
room_2.create('trogdor', {"North": room_2}, 2)

编辑:使用上述方法,这是组织房间的一种可能方式。我已将房间存放在2-dimensional list。这个解决方案很好,因为你不必担心出口的位置;该计划为您创建的每个房间都有所体现。

rooms = []
horizontal_room_count = 2
vertical_room_count = 2

class Room():

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def create(self, monster, loot):
        self.room_guard = monster
        self.exits = self.get_exits()
        self.guard_is_alive = True
        self.loot = loot

    def get_exits(self):
        x, y = self.x, self.y

        def get_room(x2, y2):
            if x2 < 0 or y2 < 0 or x2 >= horizontal_room_count or y2 >= vertical_room_count:
                return None
            return rooms[x2][y2]


        return {
                    'West': get_room(x-1, y), 
                    'East': get_room(x+1, y),
                    'North': get_room(x, y+1),
                    'South': get_room(x, y-1)
                }

rooms = [[Room(x,y) for x in range(horizontal_room_count)] for y in range(vertical_room_count)]

rooms[0][0].create('spider', loot=2)
rooms[0][1].create('trogdor', loot=2)

我们知道有一个很好的简单界面可以与房间互动。以下是使用界面在角落位置(0,0)与房间进行交互的示例。

#creating the room
>> rooms[0][0].create('evil_fairy', loot=3)

#finding the exits
>> rooms[0][0].exits

#accessing info
>> rooms[0][0].loot

答案 3 :(得分:0)

我能想象的最好方法是创建对象,然后在两个不同的步骤中创建链接。

class Room(object):
    def __init__(self, monster, loot):
        self.exits = {direction:None for direction in
                      ["North", "South", "East", "West"]}
        # rooms have no exits until you add links to them manually
        self.room_guard = monster
        self.guard_is_alive = True
        self.loot = loot
    def add_link(self, other, ordinal):
        """Creates a link between this room and another in the specified direction

        room_A.add_link(room_B, 'East')
        sets room_A.exits['East'] = room_B and room_B.exits['West'] = room_A"""

        if not hasattr(other, 'exits')
            raise ValueError("Can only link with other objects with exits")
        ordinal_map = {"North":"South", "South":"North",
                       "East":"West", "West":"East"}
        try:
            other_ordinal = ordinal_map[ordinal]
        except KeyError:
            raise ValueError("ordinal must be one of {}".format(
                    ', '.join(ordinal_map.keys())))

        self.exits[ordinal] = other
        other.exits[other_ordinal] = self

首先制作房间

map = """  A - B   C
           |       |
           D - E - F """
# bonus points if you can build a function that takes this as input and
# outputs the correct structure of rooms!!!

rooms = {key:Room(*args) for key,args in zip("ABCDEF",monster_loot_tuples)}
# monster_loot_tuples would be a list like [("Gargoyle","+1 Sword of Smiting"), ...]

然后添加链接

rooms['A'].add_link(rooms['B'], 'East')
rooms['A'].add_link(rooms['D'], 'South')
rooms['D'].add_link(rooms['E'], 'East')
rooms['E'].add_link(rooms['F'], 'East')
rooms['F'].add_link(rooms['C'], 'North')