Python 何时使用defaultdict与使用copy

Python 何时使用defaultdict与使用copy,python,Python,对于以下情况,使用副本和defaultdict方法有什么区别 base_data = {...} for item in iterable: # approach 1 <-- why wouldn't this work? data = defaultdict(lambda: base_data) # approach 2 data = deepcopy(base_data) ... 第一种方法似乎是错误的对象类型,但是有人能澄清这两种方法

对于以下情况,使用副本和defaultdict方法有什么区别

base_data = {...}

for item in iterable:

    # approach 1 <-- why wouldn't this work?
    data = defaultdict(lambda: base_data)

    # approach 2
    data = deepcopy(base_data)

    ...
第一种方法似乎是错误的对象类型,但是有人能澄清这两种方法之间的区别是什么,以及为什么这不起作用吗

deepcopy制作了一个全新的原始dict深度副本;新副本与原始副本完全分离,因此对其中一个副本的后续修改不会影响另一个副本

defaultdictlambda:base_数据生成一个dict,每当括号内的键查找失败时,该dict会插入一个值作为base_数据别名的键,因此修改任何值都会修改所有值,就像b=a然后对a或b执行变异操作会影响两者一样

defaultdict的默认构造函数应始终返回一个不可变的类型别名,因为它们不能被变异,或者是一个全新的独立可变类型,例如,对于具有不可变值的base_数据,使用defaultdictbase_dict.copy的浅层副本有效;对于具有可变值的base_数据,您需要一个深度副本来保持它们的独立性,defaultdictlambda:copy.deepcopybase_数据,或者只要将定义base_数据的文本复制到lambda中(如果足够短)

1有一个制作完全独立副本的用例,可以在不影响其他副本的情况下进行更新

正如你写的,只是没有;所有键之间共享的许多可变类型的别名基本上是无用的;您需要复制或重新构造以默认为可变值,从而生成有用的defaultdict

deepcopy制作了一个全新的原始dict深度副本;新副本与原始副本完全分离,因此对其中一个副本的后续修改不会影响另一个副本

defaultdictlambda:base_数据生成一个dict,每当括号内的键查找失败时,该dict会插入一个值作为base_数据别名的键,因此修改任何值都会修改所有值,就像b=a然后对a或b执行变异操作会影响两者一样

defaultdict的默认构造函数应始终返回一个不可变的类型别名,因为它们不能被变异,或者是一个全新的独立可变类型,例如,对于具有不可变值的base_数据,使用defaultdictbase_dict.copy的浅层副本有效;对于具有可变值的base_数据,您需要一个深度副本来保持它们的独立性,defaultdictlambda:copy.deepcopybase_数据,或者只要将定义base_数据的文本复制到lambda中(如果足够短)

1有一个制作完全独立副本的用例,可以在不影响其他副本的情况下进行更新


正如你写的,只是没有;所有键之间共享的许多可变类型的别名基本上是无用的;您需要复制或重新构造以默认为可变值,从而生成有用的defaultdict。

这不是defaultdict的实际用途,因此使用DeepCopy我不确定您的要求。两者正在创建完全不同的数据。第一个是一个包含无限多个基本数据的字典,每个数据都是同一个对象,顺便说一下,第二个仅仅相当于一个基本数据。老实说,我很难理解你的问题。他们做的事情完全不同。@juanpa.arrivillaga我明白了-我想把一个答案放在一起,说明差异,然后我会接受的。我可能对什么时候使用哪个感到困惑。这并不是defaultdict的真正用途,所以使用DeepCopy我不确定你在问什么。两者正在创建完全不同的数据。第一个是一个包含无限多个基本数据的字典,每个数据都是同一个对象,顺便说一下,第二个仅仅相当于一个基本数据。老实说,我很难理解你的问题。他们做的事情完全不同。@juanpa.arrivillaga我明白了-我想把一个答案放在一起,说明差异,然后我会接受的。我可能对什么时候使用哪个感到困惑。我明白了,所以defaultdict只有一个对象,任何对它的突变都会影响引用它的所有对象?即使查找发生在更改之前?@David542:这是因为您使用的lambda返回单个现有对象,而没有以任何方式复制它,而不是创建新对象;这和做a=b是一样的,你做的是别名,而不是副本。defaultdict的有用案例:1返回一个不可变的值,以便在更改时替换它,而不是就地修改;2根据需要构造一个新值。如果base_dict的值都是不可变的,那么defaultdictbase_dict.copy就可以了;如果没有,您可以使用defaultdictlambda:copy.deepcopybase\u dict来确保每个值都是新的,并且与其他值断开连接。啊,好的,这是一个很好的解释-谢谢!你想在你的答案中添加评论部分,我会接受它吗?@David542:重新措辞。谢谢,在某种程度上,这就像我每次都在用copybase_dict实例化一个粗糙的类。也许我应该去
我明白了,那么defaultdict只有一个对象,并且它的任何变化都会影响引用它的所有对象吗?即使查找发生在更改之前?@David542:这是因为您使用的lambda返回单个现有对象,而没有以任何方式复制它,而不是创建新对象;这和做a=b是一样的,你做的是别名,而不是副本。defaultdict的有用案例:1返回一个不可变的值,以便在更改时替换它,而不是就地修改;2根据需要构造一个新值。如果base_dict的值都是不可变的,那么defaultdictbase_dict.copy就可以了;如果没有,您可以使用defaultdictlambda:copy.deepcopybase\u dict来确保每个值都是新的,并且与其他值断开连接。啊,好的,这是一个很好的解释-谢谢!你想在你的答案中添加评论部分,我会接受它吗?@David542:重新措辞。谢谢,在某种程度上,这就像我每次都在用copybase_dict实例化一个粗糙的类。也许我应该把它变成一门课?