【问题标题】:How to reference an existing class object with no defined variable?如何引用没有定义变量的现有类对象?
【发布时间】:2016-02-14 00:17:15
【问题描述】:

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

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 变量,但直觉上这似乎会导致循环,所以我还没有触及它。

【问题讨论】:

    标签: python class python-3.x object


    【解决方案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

    【讨论】:

    • 这里的问题是会有很多其他房间,所以如果我不能直接引用它们,我最终会称它们为 room1.N.E.E.W.N.S 或其他可笑的东西。
    • @aryst0krat 那么这个问题的更大背景是什么?根据您想对房间做什么,可能有更好的方式来组织它们,但我需要知道您想对它们做什么才能提供帮助。
    • 更大的背景是它是一款基于文本的冒险游戏。就我的 Room 对象而言,我需要能够参考它们来了解玩家所在的位置、游戏对象周围的情况等。所以能够通过名称来引用它们很重要,但我宁愿不必为它们手动创建变量。他们连接的原因只是为了从一个房间移动到另一个房间。因此,如果您说向北移动,它会将您移动到房间 N 变量中的房间。
    • @aryst0krat 我明白了。请参阅我编辑的答案。希望对您有所帮助!
    • 天哪,别管我说什么。我正在以完全荒谬的方式思考这个问题。显然,无论如何我都需要为每个单独的房间编写代码,所以这些都不重要。
    【解决方案2】:

    您的 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')

    【讨论】:

    • 我觉得这个实现大概是在我现在的水平之上哈哈。我不认识 'cls' 或不理解 __new__ 函数(看起来像内置函数?)是如何被调用的,或者为什么它与 __init__ 不同,也不知道该函数作为一个整体究竟是做什么的。我会试着把它弄明白,不过如果没有别的东西,我肯定会记住它以备将来使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-15
    • 2012-11-18
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    相关资源
    最近更新 更多