Python 如何将一个字典的值设置为对另一个字典值的引用?

Python 如何将一个字典的值设置为对另一个字典值的引用?,python,dictionary,pass-by-reference,Python,Dictionary,Pass By Reference,对于我正在制作的游戏,我想创建一个对象,该对象的属性可以设置为另一个对象的属性(例如door.locked=lock.locked)。当我更新第二个对象的属性(在本例中为lock)时,第一个对象(door)的相应属性也应更新。这样,解锁门锁也将解锁车门。 我目前使用字典实现了这一点,如下所示: class Lock(): def __init___(self, locked = True): self.attributes = {'locked': locked}

对于我正在制作的游戏,我想创建一个对象,该对象的属性可以设置为另一个对象的属性(例如door.locked=lock.locked)。当我更新第二个对象的属性(在本例中为
lock
)时,第一个对象(
door
)的相应属性也应更新。这样,解锁门锁也将解锁车门。 我目前使用字典实现了这一点,如下所示:

class Lock():
    def __init___(self, locked = True):
        self.attributes = {'locked': locked}

    def toggleLock():
        self.attributes.update({'locked': not self.attributes['locked']})

class Door():
    def __init__(self, locked = False):
        self.attributes = {'locked': locked}
>>>lock1 = Lock(locked = True)
>>>door1 = Door(lock1.attributes)
那么我应该能够做到这一点:

>>>lock1 = Lock(locked = True)
>>>door1 = Door(locked = lock1.attributes['locked'])
>>>
>>>lock1.attributes['locked']
True
>>>door1.attributes['locked']
True
>>>
>>>lock1.toggleLock()
>>>lock1.attributes['locked']
False
>>>door1.attributes['locked']
False
但是,当我调用
toggleLock()
方法时,锁的状态会改变,而门的状态不会改变。字典是可变的,所以当
lock1
的字典更新时,
door1
的字典不应该更新吗?

我该如何实现它呢?

在您的代码中,您实际上并不共享同一个字典,您在Door的构造函数中创建了一个新字典,请尝试执行以下操作:

class Door():
    def __init__(self, attributes):
        self.attributes = attributes
然后这样称呼它:

class Lock():
    def __init___(self, locked = True):
        self.attributes = {'locked': locked}

    def toggleLock():
        self.attributes.update({'locked': not self.attributes['locked']})

class Door():
    def __init__(self, locked = False):
        self.attributes = {'locked': locked}
>>>lock1 = Lock(locked = True)
>>>door1 = Door(lock1.attributes)
编辑:

如果您希望拥有不同的字典,并且只共享值,那么您可能希望将值封装在一个类中,然后共享该类的一个实例:

class SharedValue(object):
    def __init__(self, val):
        self.value = val

class Lock():
    def __init___(self, locked = True):
        self.attributes = {'locked': SharedValue(locked)}

    def toggleLock():
        self.attributes['locked'].value = not self.attributes['locked'].value

class Door():
    def __init__(self, locked = False):
        if not isinstance(locked, SharedValue):
            locked = SharedValue(locked)
        self.attributes = {'locked': locked}
然后,您可以根据需要创建它,但是使用该值的代码必须更改

>>>lock1 = Lock(locked = True)
>>>door1 = Door(locked = lock1.attributes['locked'])
>>>
>>>lock1.attributes['locked'].value
True
>>>door1.attributes['locked'].value
True
顺便说一句,在你介绍的具体案例中,我个人会让Lock成为Door的成员,并通过共享属性 并制作getter,尝试从
self.attributes
获取它,如果它不包含密钥,则从
self.lock.attribute

编辑2:

添加不同解决方案的示例:

class Lock():
    def __init__(self, locked = True):
        self.attributes = {'locked': locked}

    def toggleLock(self):
        self.attributes.update({'locked': not self.attributes['locked']})

class Door():
    def __init__(self, lock_object):
        self._attributes = {'color':'Blue'}
        self.lock = lock_object

    def get_attribute(self,key):
        if key in self._attributes:
            return self._attributes[key]
        elif key in self.lock.attributes:
            return self.lock.attributes[key]
        raise KeyError(key)

    @property
    def attributes(self):
        """
        Door's attributes
        """
        # return a new dict that contains the keys of itself, and lock (and possibly more objects)
        a = {}
        a.update(self.lock.attributes)
        a.update(self._attributes)
        return a 

    def __getattr__(self, key):
        #nice addition, makes you able to do things like `if Door.locked:`
        return self.get_attribute(key)
用法示例:

>>>l=Lock()
>>>d=Door(l)
>>>d.locked
True
>>>l.toggleLock()
>>>d.locked
False
>>>d.attributes
{'color': 'Blue', 'locked': False}

一种可能的方法(至少我更喜欢)是定义一个
单例。注意,这对Python2.x是有效的,我不知道它是否在Python3.x中工作

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args)  # , **kwargs
        return cls._instances[cls]
然后将其元类化为锁类

class Lock():
    __metaclass__ = Singleton

    def __init___(self, locked = True):
        self.attributes = {'locked': locked}

    def toggleLock():
        self.attributes.update({'locked': not self.attributes['locked']})
简单地说,
Singleton
只允许您创建该对象的一个实例。第一次调用将创建一个新对象,之后的调用不会创建一个新对象,但会返回第一次调用创建的旧对象

door_1_status = Lock()  # will create a Lock object
door_2_status = Lock()  # will not crate a new Lock, but return the already created Lock object.

因此,从
Lock
类创建的所有锁将共享同一个对象,因此状态相同。

它们是两个完全独立的对象,彼此没有引用。其中一个更新会如何影响另一个?它们中由
self.attributes
命名的字典是两个完全不同的字典。但是,如果我这样做,我会将整个
lock1.attributes
字典传递到
door1
,无法分辨我引用的是哪个键(大多数对象将不止一个键)。我应该传递一个元组和键以及字典吗?(
door1=door((lock1.attributes,'locked'))
),然后拉出
door1
中给定键的值。如果您只想在两个类中共享字典中的特定项,您需要它们都指向同一个对象实例,我只需将该值包装在一个类中,我将用一个例子来编辑答案你能举一个例子说明你如何使用@property吗?现在添加了一个,注意你可以使用getattr(如示例中所示)来轻松访问它