[英]Creating a new python dict from existing dicts with different keys but same ids
我有一个复合字典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 (包括不同的键名)的功能,即使这些键具有不同的名称,这些键也指向内存中的同一点?
我相信可能是其他原因导致值的id
更改,也许您在测试id
之前对d
字典做了一些其他赋值,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)
由于上述原因,我们不建议再次这样做。
此类将像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
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.