我设置了dict2 = dict1。当我编辑dict2时,原来的dict1也改变了。为什么?

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = dict1
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key2': 'WHY?!', 'key1': 'value1'}

当前回答

如果你的字典是映射类型,你不能.copy()它,但你可以

dict2 = dict1 | {}

它有点模糊,与copy.copy(dict1)相比,我不能说它的性能如何,但它非常简洁。

其他回答

除了其他提供的解决方案,您还可以使用**将字典集成到一个空字典中,例如:

Shallow_copy_of_other_dict = {**other_dict}。

现在您将拥有other_dict的“浅”副本。

应用于你的例子:

>>> dict1 = {"key1": "value1", "key2": "value2"}
>>> dict2 = {**dict1}
>>> dict2
{'key1': 'value1', 'key2': 'value2'}
>>> dict2["key2"] = "WHY?!"
>>> dict1
{'key1': 'value1', 'key2': 'value2'}
>>>

指针:浅拷贝和深拷贝的区别

当你赋值dict2 = dict1时,你并没有创建一个dict1的副本,结果是dict2只是dict1的另一个名字。

要复制像字典这样的可变类型,使用copy模块的copy / deepcopy。

import copy

dict2 = copy.deepcopy(dict1)

正如其他人解释的那样,内置字典不能做你想做的事情。但是在Python2(可能还有python3)中,你可以很容易地创建一个ValueDict类,使用=进行复制,这样你就可以确保原始的类不会改变。

class ValueDict(dict):

    def __ilshift__(self, args):
        result = ValueDict(self)
        if isinstance(args, dict):
            dict.update(result, args)
        else:
            dict.__setitem__(result, *args)
        return result # Pythonic LVALUE modification

    def __irshift__(self, args):
        result = ValueDict(self)
        dict.__delitem__(result, args)
        return result # Pythonic LVALUE modification

    def __setitem__(self, k, v):
        raise AttributeError, \
            "Use \"value_dict<<='%s', ...\" instead of \"d[%s] = ...\"" % (k,k)

    def __delitem__(self, k):
        raise AttributeError, \
            "Use \"value_dict>>='%s'\" instead of \"del d[%s]" % (k,k)

    def update(self, d2):
        raise AttributeError, \
            "Use \"value_dict<<=dict2\" instead of \"value_dict.update(dict2)\""


# test
d = ValueDict()

d <<='apples', 5
d <<='pears', 8
print "d =", d

e = d
e <<='bananas', 1
print "e =", e
print "d =", d

d >>='pears'
print "d =", d
d <<={'blueberries': 2, 'watermelons': 315}
print "d =", d
print "e =", e
print "e['bananas'] =", e['bananas']


# result
d = {'apples': 5, 'pears': 8}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
d = {'apples': 5, 'pears': 8}
d = {'apples': 5}
d = {'watermelons': 315, 'blueberries': 2, 'apples': 5}
e = {'apples': 5, 'pears': 8, 'bananas': 1}
e['bananas'] = 1

# e[0]=3
# would give:
# AttributeError: Use "value_dict<<='0', ..." instead of "d[0] = ..."

请参考这里讨论的左值修改模式:Python 2.7 -用于左值修改的干净语法。关键的观察是,str和int在Python中表现为值(即使它们实际上是不可变的对象)。在观察的同时,请注意str或int并没有什么神奇的特殊之处。dict可以以几乎相同的方式使用,我可以想到ValueDict有意义的许多情况。

另一种更简洁的方法是使用json。参见下面的代码

>>> a = [{"name":"Onkar","Address": {"state":"MH","country":"India","innerAddress":{"city":"Pune"}}}]
>>> b = json.dumps(a)
>>> b = json.loads(b)
>>> id(a)
2334461105416
>>> id(b)
2334461105224
>>> a[0]["Address"]["innerAddress"]["city"]="Nagpur"
>>> a
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Nagpur'}}}]
>>> b
[{'name': 'Onkar', 'Address': {'state': 'MH', 'country': 'India', 'innerAddress': {'city': 'Pune'}}}]
>>> id(a[0]["Address"]["innerAddress"])
2334460618376
>>> id(b[0]["Address"]["innerAddress"])
2334424569880

要创建另一个字典,请在同一个字典对象上执行json.dumps()和json.loads()。你将有单独的字典对象。

起初,这也让我感到困惑,因为我来自C语言背景。

在C语言中,变量是内存中具有已定义类型的位置。对变量赋值会将数据复制到变量的内存位置。

但在Python中,变量更像是指向对象的指针。因此,将一个变量赋值给另一个变量并不会产生复制,它只是使变量名指向相同的对象。