【问题标题】:Make dict comprehension return by reference通过引用使dict理解返回
【发布时间】:2018-01-25 01:57:15
【问题描述】:
  • 我有以下字典:original = {a:1, b:2}
  • 然后我运行字典理解:extracted = {k:v for (k,v) in original.items() if k == 'a'}
  • 返回以下字典:{a:1}
  • 如果我改变extracted['a'] = 2original['a'] 仍将等于1

问题:

有没有办法让上面的dict理解通过引用返回?例如extracted['a'] = 2 将导致original['a'] = 2

我不希望涉及更改 original 字典。

【问题讨论】:

  • 简短回答:否。(无论如何,如果不更改您的数据类型 - 如果 extracted['a']original['a'] 都是列表,那么您可以使它们相同对象)。
  • ...如果您真的想要在远处进行幽灵般的动作,我想您可以实现自己的dict-like 对象,该对象会了解原始对象并对其进行更新在__setitem__()。但这会打破人们对您的代码的期望,否则将是一个坏主意。
  • 用类 C 语言的数据模型来思考 Python 的数据模型很少有成果。所以忘记“通过引用”的东西。有关此主题的更多信息,请参阅由 SO 资深人士 Ned Batchelder 撰写的Facts and myths about Python names and values
  • OTOH,如果你让这些 dict 值可变,那么你可以改变它们,而不是分配给它们。例如,original = {'a':[1], 'b':[2]}; extracted = {k:v for k,v in original.items() if k == 'a'}; extracted['a'][0] = 3; print(original) 打印 {'a': [3], 'b': [2]}

标签: python dictionary dictionary-comprehension


【解决方案1】:

如果您的新字典属于添加了所需逻辑的自定义类型:

class MappedDict(dict):
    def __init__(self, orig, *args, **kwargs):
        self.__orig = orig
        dict.__init__(self, *args, **kwargs)
    def __setitem__(self, k, v):
        self.__orig[k] = v
        return dict.__setitem__(self, k, v)

d = {'a': 1, 'b': 2}
md = MappedDict(d, {k: v*2 for (k,v) in d.items()})
md['a']=5

...将使dmd'a' 具有5 的值,而b 将有所不同(前者为2,后者为4)。

【讨论】:

  • “显式优于隐式”,我似乎记得someone saying。 :)
  • 但如果您使用问题{k:v for (k,v) in original.items() if k == 'a'} 中的条件理解,并且您更改了md['b'],即使md 没有b 元素也会传播到原始内容(根据定义,它被排除在外)。我不确定这是不需要或想要的,我只是想提一下。 :)
【解决方案2】:

不,推导式总是返回一个浅拷贝(嗯,实际上它是一个包含对您迭代的值的引用的新对象)。然而它只是一个浅拷贝,所以如果你使用可变类型作为值并且你在原地更改它们,更改将传播到原始对象。

>>> original = {'a':[], 'b':[]}
>>> extracted = {k:v for (k,v) in original.items() if k == 'a'}
>>> extracted['a'].append(1)  # change one value in extracted in-place
>>> original                  # original also changed
{'a': [1], 'b': []}
>>> extracted
{'a': [1]}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-13
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    相关资源
    最近更新 更多