如何引用没有定义变量的现有类对象?

时间:2016-02-14 00:17:16

标签: python class python-3.x object

我正在尝试使用类对象的函数来创建新的类对象并遇到问题。这是我到目前为止的代码:

class Room(object):
    def __init__(self, name):
        self.name = name
        self.N = None
        self.E = None
        self.S = None
        self.W = None
    '''relevant code'''
    def north(self,room):
        self.N = Room(room)
        self.N.S = self
    def south(self,room):
        self.S = Room(room)
        self.S.N = self

所以我至少想要其中一个打印语句

room1 = Room('room1')
room1.north('room2')

print(room2.S)
print(Room(room2).S)
print(Room('room2').S)

吐出'room1',但前两个不起作用,因为room2作为变量尚未定义,而最后一个不起作用,因为它似乎是在创建一个新对象而不是引用现有的,所以只打印默认的“无”。

是否存在一种引用现有对象而没有设置变量的方法?或者我唯一的选择是做这样的事情?

    def north(self,room):
        roomDict[room] = Room(room)
        self.N = roomDict[room]
        self.N.S = self

编辑:我意识到我应该调用新的Room的south()函数而不是直接更改S变量,但这看起来很直观,因为它会导致循环,所以我还没有触及它。 / em>的

2 个答案:

答案 0 :(得分:1)

*根据OP的澄清*

进行编辑

如果您想要引用大量对象而不将它们绑定到变量,那么dict就可以了。

您可以使用@ Berci的解决方案。但请注意,使用该解决方案,如果您已经有一个名为foo的房间,则无法再次调用Room('foo')来覆盖它 - 这样做只会返回原来的foo房间。要覆盖现有会议室,您必须先del Room.roomDict['foo'],然后拨打Room('foo')。这可能是你想要的,但也许不是。

下面的实现不那么奇特,不需要__new__(实际上,Berci的解决方案也不需要__new__,并且可以在__init__完成所有内容:

class Room:
    registry = {}
    def __init__(self, name):
        self.registry[name] = self
        # the rest of your __init__ code

如果您希望房间不可覆盖,就像在Berci的解决方案中一样,只需添加两行:

class Room:
    registry = {}
    def __init__(self, name):
        if name in self.registry:
            raise ValueError('room named "{}" already exists'.format(name))
        self.registry[name] = self

没有必要在registry内嵌套Room。如果你愿意,你可以把它变成一个外部词典。将注册表作为类属性的优点是,Room对象可以在不知道其全局名称的情况下以self.registry的形式访问它。 (轻微)的缺点是,每次访问时,您都需要输入Room.registrysomeroom.registry,而不仅仅是registry

答案 1 :(得分:0)

你的dict解决方案可以起作用。使用类级roomDictnew构造函数不创建由其名称引用的现有对象:

class Room(object):
    roomDict = {}
    def __new__(cls, name):
        if name in cls.roomDict:
            return cls.roomDict[name]
        self = object.__new__(cls, name)  # here the object is created
        cls.roomDict[name] = self
        return self
    def __init__(self, name):
        ...

之后你可以将room2称为Room('room2')