繁体   English   中英

从具有不同键但相同ID的现有字典创建新的python字典

[英]Creating a new python dict from existing dicts with different keys but same ids

我有一个复合字典d ,它是由一组组件字典d1d2构建的:

d1 = {'key1': 4}
d2 = {'key2': 5}
d = {}
d['altname_key1'] = d1['key1']
d['altname_key2'] = d2['key2']

我试图完成的行为是使d键的更改自动传播到d1d2的更改。 上面的代码没有这种行为,可以通过比较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字典的值将更改,但d1d2不会更改。 范例-

>>> 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM