我有一个复合词典 d ,它是由一组组件词典构建的, d1 和 d2 :
d1 = {'key1': 4}
d2 = {'key2': 5}
d = {}
d['altname_key1'] = d1['key1']
d['altname_key2'] = d2['key2']
我想要完成的行为是更改 d 的键,以自动传播到 d1 和 d2 中的更改。上面的代码不是这样的,可以通过比较id来验证:
id(d['altname_key1']) == id(d1['key1'])
True
id(d['altname_key2']) == id(d2['key2'])
True
d['altname_key1'] = 17
id(d['altname_key1']) == id(d1['key1'])
False
如果我的复合词典只是单个组件和的组合,如果我没有更改键名,那么我正在寻找的行为可以实现:
d = d1
d['key1'] = 45
id(d['key1']) == id(d1['key1'])
True
python是否具有启用复合词典 d 的功能,包括不同的键名,以便键指向内存中的相同点,即使键具有不同的名称?
答案 0 :(得分:2)
我相信其他一些东西可能会导致id
的值发生变化,也许你在测试d
之前对id
字典进行了一些其他的赋值,python中的数字是不可变的,所以两个不同的数字不会有相同的id
。
当你这样做时 - d['altname_key1'] = d1['a']
- Python通过赋值传递,这意味着d1['a']
引用的引用按值传递。示例 -
>>> d = {'a':[1,2]}
>>> d2 = {'b':[3,4]}
>>> d3 = {}
>>> d3 ['aa'] = d['a']
>>> d3['bb'] = d2['b']
>>> d3
{'bb': [3, 4], 'aa': [1, 2]}
>>> id(d3['aa']) == id(d['a'])
True
>>> d3['aa'].append(5)
>>> d3
{'bb': [3, 4], 'aa': [1, 2, 5]}
>>> d
{'a': [1, 2, 5]}
所以你想要实现的目标确实有效。
但是这个给出,我想建议不要对同一个可变对象保持多个引用,因为这个方法可能导致神秘的错误,有些代码可能会错误地更新d
字典,即使你不想要它和它可以导致相同的变化反映在d1中。调试问题很难。
此外,如果您在d
上执行作业,此方法会中断,在这种情况下,d
字典的值会发生变化,但d1
或d2
不会更改。示例 -
>>> d3['aa'] = [1]
>>> d3
{'bb': [3, 4], 'aa': [1]}
>>> d
{'a': [1, 2, 5]}
您可能想重新考虑您要设计的内容。
关于为什么在执行以下操作时获得所需的行为 -
d = d1
d['key1'] = 45
id(d['key1']) == id(d1['key1'])
True
这是因为d
是对d1
字典对象的引用,所以它们基本上指向相同的字典。因此d['key1']
始终为d1['key1']
。您可以执行以下操作以查看它们是相同的参考 -
id(d) == id(d1)
由于上述原因,不会再推荐这一点。
答案 1 :(得分:1)
这个类将像ChainMap一样,除了它将尊重你指定的备用键映射。它适用于Python 2.7和Python 3.3 +。
from __future__ import print_function
try:
from collections import ChainMap # Python 3
except ImportError:
from ConfigParser import _Chainmap as ChainMap # Python 2
class ChainMapWithAltKeys(ChainMap):
def __init__(self, *maps, **kwargs):
try:
super(ChainMapWithAltKeys, self).__init__(*maps)
except TypeError: # Python 2
ChainMap.__init__(self, *maps) # Python 2
self.altkeymap = kwargs.get('altkeymap', {})
def __getitem__(self, key):
if key in self.altkeymap:
key = self.altkeymap[key]
try:
return super(ChainMapWithAltKeys, self).__getitem__(key)
except TypeError: # Python 2
return ChainMap.__getitem__(self, key) # Python 2
dict_one = {'a': 1, 'b': 2, 'c': 3, 'samekey': 'diffval_one'}
dict_two = {'x': 24, 'y': 25, 'z': 26, 'samekey': 'diffval_two'}
altkeymap = {'alpha': 'a', 'zulu': 'z'}
cmwak = ChainMapWithAltKeys(dict_one, dict_two, altkeymap=altkeymap)
print(cmwak['a']) # 1
print(cmwak['alpha']) # 1
print(cmwak['b']) # 2
print(cmwak['y']) # 25
print(cmwak['z']) # 26
print(cmwak['zulu']) # 26
print(cmwak['samekey']) # diffval_one
请注意,当一个键位于多个dict中时,该值取自首先传递的dict;具体来说,按顺序检查cmwak.maps中的每个映射,直到找到密钥。阅读ChainMap了解详情;那里的所有内容都适用于ChainMapWithAltKeys
。