【问题标题】:Python defaultdictPython 默认字典
【发布时间】:2021-01-04 12:14:51
【问题描述】:

我发现了一些我无法理解的奇怪东西。 是这样的:

from collections import defaultdict
a = defaultdict(lambda: len(a))

这只是代码的一部分,上面的代码从来没有定义过'a'。

问题是:

  • 是否可以按原样使用defaultdict,而不是事先指定变量?
  • 如果可能,该代码的含义是什么?

【问题讨论】:

    标签: python lambda collections defaultdict


    【解决方案1】:

    也许最好用一个例子来解释:

    >>> a = defaultdict(lambda: len(b))
    >>> b = 'abcd'
    >>> a[0]
    4
    

    如您所见,可以在lambda 中使用b,即使此时b 尚不存在。重要的是blambda 执行时存在。此时,Python 将查找名为 b 的变量并使用它。


    另请注意,原始代码不一定使用 defaultdict 本身的长度。它只是评估此时a 的任何内容。看这个例子:

    >>> a = defaultdict(lambda: len(a))
    >>> a['a']
    0
    >>> a['b']
    1
    

    到目前为止,一切都很好。但是然后重命名一些东西:

    >>> x = a
    >>> a = []
    >>> x['c']
    0
    >>> x['d']
    0
    

    现在默认字典被命名为x,但它不使用len(x)。它仍然使用len(a)。如果您将 defaultdict 发送到 a 没有任何意义的函数,则此警告可能会变得很重要。

    【讨论】:

    • 非常感谢您的回复。无论如何,但是在第 2 块,为什么 a['a']=0?
    • 因为在评估 a['a'] 时,len(a) 仍然是 0。在得到 lambda (0) 的结果后,该值存储在 a['a']
    • 哦,现在我明白了!感谢您的大力帮助:)
    【解决方案2】:

    你说的是默认字典,当我尝试用一​​个键做某事但它不存在时,使用这个 lambda 作为键的初始值。因为你的 lambda 使用的是(即它自己的字典)并且你说它的长度。这意味着当您使用不在字典中的键执行操作时,字典将使用 lambda 代替,或者在这种情况下使用字典的长度作为值

    from collections import defaultdict
    a = defaultdict(lambda: len(a))
    
    a['one'] += 5 #here dict length is 0 so value is 0 + 5 = 5
    a['two'] += 2 #jere dict length is 1 so value is 1 + 2 = 3
    a['three'] += 1 #here dict length is 2 so value is 2 + 1 = 3
    print(a.items())
    print(a['newval']) #here newval doesnt exist so will use default value which is length of dict I.E 3
    

    输出

    dict_items([('one', 5), ('two', 3), ('three', 3)])
    3
    

    【讨论】:

    • "使用这个 lambda 作为键的初始值。"更好的措辞,调用这个函数来生成键的值
    【解决方案3】:

    defaultdict 的工作原理如下。假设您有一个列表字典,并且您正在为可能不存在的键设置值。在这种情况下,你会做这样的事情:

    d = dict()
    if some_key not in d:
        d[some_key] = list()
    d[some_key].append(some_value)
    

    defaultdict 通过传递一个可调用对象自动为您执行此操作,例如,intlistset,它将调用 int()(默认值 0)、list()(默认值为空)列表)和set()(默认值空集)分别。您的 lambda 也是一个可调用的,它返回整数,因此您将拥有一个带有 int 值的 dict。但是你从表达式中得到的值将取决于字典的大小。

    你可以a = defaultdict(lambda: len(a))吗?

    是的,你可以。 lambda 在调用之前不会执行,此时它将查找名称 a。比较这两种情况。

    f = lambda: len(a)
    a = defaultdict(f)
    a[0]                  # this is when the lambda is called for the first time
    

    但是,

    g = lambda: len(b)
    g()                   # this will raise a NameError
    b = defauldict(g)
    

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 2021-12-20
      • 2021-07-27
      • 1970-01-01
      • 2019-08-11
      • 2016-01-28
      • 1970-01-01
      • 2016-06-25
      • 2011-12-14
      相关资源
      最近更新 更多