Python:更新引用值

Python:更新引用值,python,pointers,dictionary,reference,mutability,Python,Pointers,Dictionary,Reference,Mutability,以下是我认为它应该如何发挥作用: dictionary = {'k1': {'a': 'b'}, 'k2': [0, 1]} pointer = dictionary['k1'] print pointer >>> {'a': 'b'} pointer.update({'a': 'c'}) print dictionary >>> {'k1': {'a': 'c'}, 'k2': [0, 1]} 以下几点让我感到沮丧: pointe

以下是我认为它应该如何发挥作用:

dictionary = {'k1': {'a': 'b'}, 'k2': [0, 1]}  
pointer = dictionary['k1']  
print pointer  
>>> {'a': 'b'}  
pointer.update({'a': 'c'})  
print dictionary  
>>> {'k1': {'a': 'c'}, 'k2': [0, 1]} 
以下几点让我感到沮丧:

pointer = dictionary['k2']
print pointer
>>> [0, 1]
pointer.update([2, 3])
>>> AttributeError: 'list' object has no attribute 'update'  
我知道列表没有更新功能,我知道我可以执行以下操作:

pointer[0] = 2
dictionary['key']['key']['key']['key'] 
。。。但我希望有一个更通用的选项来更新引用值,因此对象仍然属于字典,但值已更改

原因是我有一个嵌套字典,看起来像:

pointer[0] = 2
dictionary['key']['key']['key']['key'] 
我的问题并不是针对列表是否有更新功能,而是问是否有更干净的方法来引用和更改深度嵌套字典中的值,因此最好将其存储在引用值中,而不是每次我要为其分配某个值时都将其全部键入

谢谢

编辑:修复了第一个示例中的语法
EDIT2:让我澄清一下:我知道列表没有
更新功能,而是询问通用参考值更新

编辑3:简化问题从错误消息中可以明显看出,
列表没有
更新方法。这并不意味着你不能改变它的内容,你只需要做不同的事情

pointer[:] = [2, 3]
你可以做一个通用的更新函数,但我不确定它有多有用

def update(pointer, values):
    if isinstance(pointer, list):
        pointer[:] = values
    else:
        pointer.update(dict(values))
编辑:看来您只对更新叶节点感兴趣,所以我不明白为什么下面的内容不够。只要
指针
设置为可变对象,您就可以更改该对象,并且它也会在原始字典中更改。唯一不能做的就是直接重新分配它,因为这样会重新分配引用并断开与字典的连接

pointer = dictionary['key1']['key2']['key3']['key4']
# pointer = [2, 3]   # doesn't work
pointer[:] = [2, 3]  # works
print dictionary['key1']['key2']['key3']['key4']

没有这样的事。参照指向对象,而不是对象内部的位置。时期这是Python对象模型的基本部分

如果您愿意,可以编写一个表示这样一个位置的类:

class AttributeReference:
    def __init__(self, obj, attr):
        self.obj = obj
        self.attr = attr

    def set(self, value):
        setattr(self.obj, self.attr, value)

    # add get() and del() and other methods to your heart's content 


class ElementReference:
    def __init__(self, obj, key):
        self.obj = obj
        self.key = key

    def set(self, value):
        self.obj[self.key] = value

    # add get() and del() and other methods to your heart's content
然后可以使用这样的对象而不是Python引用。 然而,它的使用相当笨拙,因此使用它的门槛相当高。
好的一面是,嵌套的深度完全无关。如果您想“引用”到
字典['k1']['k2']['k3']['k4']
,这就可以了:
ElementReference(字典['k1']['k2']['k3'],'k4')

您对指针有误解,尤其是在Python中如何标记和访问变量

首先,像C这样的低级语言中的“指针”只是一个包含内存地址的整数。通过特殊语法,
*指针
,您可以指示要访问内存位置的数据,而不是表示该位置的整数。为什么要对整数进行运算?仔细阅读指针运算,解释超出了这个答案的范围

包括Python在内的许多语言都假设您永远不需要直接对指针进行操作,因此,尽管Python变量名(如名为
pointer
的变量)有一个与其相关的内存地址(我不会在这里讨论堆栈与堆,同样,超出了范围),但Python会将其抽象出来,使您作为开发人员无法理解。在Python中,使用变量名,您将始终直接访问数据

当您直接访问数据时,必须将该数据视为正确的类型。如果不这样做,您将遇到与您看到的错误类似的错误。您可以“更新”指针,但这只是更改指针指向的内存位置,而不是更改该位置的数据,因此不会反映在
字典中

为了消除一些混淆,将Python中的变量名视为“标签”(文档使用了我相信的这个术语)。2个标签可能指向具有函数和属性的同一数据段,但标签本身不是具有函数和属性的对象


其他人已经为您的列表和dict示例提出了具体的解决方案。我希望这能解释你所看到的“为什么”。

仍然不确定我是否完全理解你的问题,但这里有两种方法。假设你有一个这样的口述:

d = {'level1': {'level2': {'level3': {'level4': [1, 2, 3]}}}}
d['level1']['level2']['level3']['level4']
为您提供最内层列表的参考。如果您将其存储,您可以使用它执行任何操作:

innerValue = d['level1']['level2']['level3']['level4']
innerValue.append(4)

>>> d
{'level1': {'level2': {'level3': {'level4': [1, 2, 3, 4]}}}}
但是,正如其他人在评论中所指出的,您在这里修改的是列表。列表不“知道”它在字典中。您可以对该列表执行的操作与对任何其他列表执行的操作相同。如果它不是一个列表,而是其他类型的对象,同样的道理也适用:当它在dict中时,你可以对它做什么,就像你在其他地方可以对它做什么一样。如果要就地更新对象,则不会通知dict。所以没有一种“通用”的更新方法是基于对象在dict中这一事实的,因为对象不知道它们是否在dict中

另一种方法是存储对包含要修改的元素的dict的引用。然后,您可以使用正常dict操作更改其值:

innerDict = d['level1']['level2']['level3']
innerDict['level4'] = "Some other value"

>>> d
{'level1': {'level2': {'level3': {'level4': 'Some other value'}}}}
这个方法是“通用”的,因为它不依赖于内部目录中存储了什么类型的值。这里发生的事情是,您正在更新内部目录,使其值指向一个新对象。但是请注意,这会创建一个新对象,因此它不会修改原来的列表(甚至可以像在我的示例中那样更改它的值类型)。它会就地修改内部dict(通过为其中一个键指定新值)


你的问题并不清楚你想达到什么目的,但有两种方法可以将某种引用存储在深度嵌套的dict中,然后将其搞乱。

阅读错误消息。这就是全部。(没有变量ref