【问题标题】:What is the difference between the following two implementaions of an arbitrary nested defaultdict of defaultdict in Python?Python中defaultdict的任意嵌套defaultdict的以下两个实现有什么区别?
【发布时间】:2021-05-30 04:49:56
【问题描述】:

我正在使用来自this answer 的 sn-p,更具体地说,是使用 lambda 的那个。

我一直在尝试使用 Python 3.8 中的 := 运算符来实现这一点,最终我得到了两个不同的实现,我相信这两个都可以满足我的需求。

片段 1(使用预先定义的 lambda,与链接答案中的 sn-p 相同)

from collections import defaultdict
from pprint import pprint

func = lambda:defaultdict(func)

infinite_nested_dicts_one = func()

infinite_nested_dicts_one[1][2][3][4][5]['a'] = '12345a'
infinite_nested_dicts_one[1][2][3][4][5]['b'] = '12345b'

print(infinite_nested_dicts_one[1][2][3][4][5]['a'])  # '12345a'
print(infinite_nested_dicts_one[1][2][3][4][5]['b'])  # '12345b'
pprint(infinite_nested_dicts_one)

输出 1

12345a
12345b
defaultdict(<function <lambda> at 0x000001A7405EA790>,
            {1: defaultdict(<function <lambda> at 0x000001A7405EA790>,
                            {2: defaultdict(<function <lambda> at 0x000001A7405EA790>,
                                            {3: defaultdict(<function <lambda> at 0x000001A7405EA790>,
                                                            {4: defaultdict(<function <lambda> at 0x000001A7405EA790>,
                                                                            {5: defaultdict(<function <lambda> at 0x000001A7405EA790>,
                                                                                            {'a': '12345a',
                                                                                             'b': '12345b'})})})})})})

片段 2(使用赋值运算符)

from collections import defaultdict
from pprint import pprint

infinite_nested_dicts_two = (func:=defaultdict(lambda:func))

infinite_nested_dicts_two[1][2][3][4][5]['a'] = '12345a'
infinite_nested_dicts_two[1][2][3][4][5]['b'] = '12345b'

print(infinite_nested_dicts_two[1][2][3][4][5]['a'])  # '12345a'
print(infinite_nested_dicts_two[1][2][3][4][5]['b'])  # '12345b'
pprint(infinite_nested_dicts_two)

输出 2

12345a
12345b
defaultdict(<function <lambda> at 0x0000022F1A0EA790>,
            {1: <Recursion on defaultdict with id=2401323545280>,
             2: <Recursion on defaultdict with id=2401323545280>,
             3: <Recursion on defaultdict with id=2401323545280>,
             4: <Recursion on defaultdict with id=2401323545280>,
             5: <Recursion on defaultdict with id=2401323545280>,
             'a': '12345a',
             'b': '12345b'})

在这两种情况下,为[1][2][3][4][5]['a'][1][2][3][4][5]['b'] 访问最外层的defaultdict 都会得到相同的输出。

所以问题是

  • 为什么pprint 输出不同?
  • 这些是否相同?
  • 它们是否都是任意嵌套的defaultdictdefaultdict
  • 我是否遗漏了一些细节?

PS:

我知道使用:= 的语法等价物是infinite_nested_dicts_two = (func:=lambda:defaultdict(func))()

如果需要任何说明,请告诉我。非常感谢。

【问题讨论】:

  • 你好。我只是想让你知道没有必要说“非常感谢。”。出于多种原因删除它们是常见的 SO 策略,请参阅Should 'Hi', 'thanks', taglines, and salutations be removed from posts?。此外,无需在帖子正文中包含“如果需要任何澄清,请告诉我。”。 SO 的常见做法是,如果需要任何澄清,其他用户将在 cmets 中提出要求。

标签: python dictionary recursion defaultdict


【解决方案1】:

您的第二个版本将defaultdict instance 分配给func(并且冗余分配给infinite_nested_dicts_two)。因此,它没有使用func(这不是一个函数!)作为其默认生成函数,而是使用一个始终返回func的常量函数——,字典本身 是默认值。必要的结果是 pprint 揭示的高度递归结构,因为每一级索引都向同一个 object 添加一个键并返回。

【讨论】:

  • 谢谢Whovian ;),我现在理解得更好了,所以它可能是infinite_nested_dicts_one = defaultdict(lambda:infinite_nested_dicts_one),我相信我会得到相同的输出吗?那么这是否有点类似于返回[[...]]a = a[0] = [0] 的结果?如果您能澄清这一点,我将不胜感激
  • 另一个问题,是否会因此而增加内存使用量,或者因为它们都是引用,所以没关系?抱歉问题,再次感谢
  • @Alice:是的,这个赋值是等价的,而且对象是循环的。一般来说,一个字典中的附加条目比多个字典使用更少的内存,但由于语义完全不同,我不确定这是否重要。
猜你喜欢
  • 2013-10-11
  • 2021-12-01
  • 2023-03-26
  • 1970-01-01
  • 2021-11-28
  • 2022-01-12
相关资源
最近更新 更多