在Python中创建Defaultdict的Defaultdict

Python 有内置的容器,如 dict、list、set 和 tuple,它们有一个通用的思想体系。为了扩展或改进这些通用的容器,Python 提供了一个模块,引入了专门的容器数据类型,称为 Python Collections。

其中一个专门的容器数据类型是defaultdict ,它是默认的 Python 字典 (dict) 的一个很好的替代品 (和一个子类)。使用defaultdict ,你可以提供一个factory 函数来提供缺失的值 (而不是一个KeyError 异常或消息)。

因此,如果键在字典中不存在,factory 函数被调用并返回一个值,而不是引发一个KeyError 异常。

使用defaultdict 可能相对简单,但使用defaultdictdefaultdict 可能会令人困惑。本文将解释如何在不引起任何错误的情况下创建defaultdictdefaultdict ,以及它的内在操作是如何发生的。

使用lambda 在 Python 中创建 Defaultdict 的 Defaultdict

为了利用Python集合和固有的defaultdict ,你可以使用Python表达式导入collection 模块:

from collections import defaultdict

注意defaultdictdict 类的一个子类,下面的Python表达式可以检查这个子类:

issubclass(defaultdict, dict)

输出:

True

使用dict ,当一个不存在的键被传递到字典中时,会触发__missing__ 方法,它持有的default_factory 属性被设置为None ,因此导致KeyError 异常。然而,通过default_dict ,当一个不存在的键被传递到 dictionary 时,它触发了__missing__ 方法的default_factory 属性,它持有一个factory ,返回一个缺省值。

例如,我们可以有一个defaultdict dictionary,它持有factory 函数,list ,当传递一个不存在的键时,它返回一个空列表。

from collections import defaultdict
ddict = defaultdict(list)
print(ddict["one"])

输出:

[]

尽管ddict 没有键one ,但由于传递了factory 函数,它返回的值是一个空列表。它甚至在这样的表达式后创建了键。

from collections import defaultdict
ddict = defaultdict(list)
print(ddict["one"])
print(ddict["two"].append(1))
print(ddict)

输出结果:

[]
defaultdict(<class 'list'>, {'one': [], 'two': [1]})

所以,在ddict["one"]ddict["two"].append(1) 语句之后,它创建了各自的键和基于list 函数的相应值。对于第二个Python语句,它基于default_factory 属性函数创建了空列表,然后将值1 附加到其中。

defaultdict 数据类型中典型的数值分组可以与dict 数据类型的处理方式不同。

sentence = 'the man loves oranges, but also cares a great deal about apples'
letterStore = dict()
for i in sentence:
    if k not in letterStore:
        letterStore[i] = 1
        continue
    letterStore[i] += 1
print(letterStore.items())

输出:

dict_items([('t', 4), ('h', 1), ('e', 7), (' ', 11), ('m', 1), ('a', 9), ('n', 2), ('l', 4), ('o', 4), ('v', 1), ('s', 5), ('r', 3), ('g', 2), (',', 1), ('b', 2), ('u', 2), ('c', 1), ('d', 1), ('p', 2)])

上述的字母分组可以通过使用defaultdict 来轻松完成。与其让代码块检查字母是否已经在letterStore 绑定中创建初始编号,我们可以使用defaultdict ,通过factory 函数 –int 来实现。

from collections import defaultdict
sentence = 'the man loves oranges, but also cares a great deal about apples'
letterStore = defaultdict(int)
for i in sentence:
    letterStore[i] += 1
print(letterStore.items())

输出:

dict_items([('t', 4), ('h', 1), ('e', 7), (' ', 11), ('m', 1), ('a', 9), ('n', 2), ('l', 4), ('o', 4), ('v', 1), ('s', 5), ('r', 3), ('g', 2), (',', 1), ('b', 2), ('u', 2), ('c', 1), ('d', 1), ('p', 2)])

所以,通过这个,我们知道,当一个键不存在时,__missing__ 方法被调用。它的属性default_factory 也被触发了,它持有一个返回值的函数。

然而,我们可以创建一个defaultdictdefaultdict 吗?是的,但我们如何才能做到呢?因为如果你把一个defaultdict 传给另一个defaultdict ,就会引起错误。

from collections import defaultdict
d = defaultdict(defaultdict(int))
print(d)

输出:

Traceback (most recent call last):
  File "c:UsersUSERDesktopJStest.py", line 3, in <module>
    d = defaultdict(defaultdict(int))
TypeError: first argument must be callable or None

当我们运行代码时,抛出了一个TypeError ,而这是由于d = defaultdict(defaultdict(int)) ,这一行说的是first argument must be callable or None

通过这些信息,我们可以推断出,我们没有传递一个可调用的(一个函数)或None(default_factory 持有的默认值),这是因为defaultdict(int) 是不可调用的。然而,它是一个'collections.defaultdict'

因此,我们需要找到一种方法来传递一个可调用的东西,这就是lambda 的作用。

lambda 我们可以创建一个可以被调用的匿名函数(一个可调用的)。因此,对于上层的 ,我们可以传递一个指向 的 函数,当我们传递一个不存在的键时,它将被调用。defaultdict defaultdict(int) lambda

lambda 函数调用内部defaultdict 中的factory 函数,并返回其值,该值将被设置为键值。

from collections import defaultdict
d = defaultdict(lambda: defaultdict(int))
print(d)

输出:

defaultdict(<function <lambda> at 0x000001F6B9383E20>, {})

为了表明它工作正常,我们可以使用平方符号访问顶层的defaultdict 和内层的defaultdict ,以查看它们的默认值,这些值应分别传递给lambdaint 函数。

print(d[0])
print(d[0][0])

输出结果:

defaultdict(<class 'int'>, {})
0