Collections.defaultdict 与普通字典的区别

2024-12-13 08:37:00
admin
原创
92
摘要:问题描述:我读过 Python 文档中的示例,但仍然不明白这个方法是什么意思。有人能帮忙吗?以下是 Python 文档中的两个示例>>> from collections import defaultdict >>> s = 'mississippi' >>&...

问题描述:

我读过 Python 文档中的示例,但仍然不明白这个方法是什么意思。有人能帮忙吗?以下是 Python 文档中的两个示例

>>> from collections import defaultdict

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> d.items()
dict_items([('m', 1), ('i', 4), ('s', 4), ('p', 2)])

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

这些参数intlist用途是什么?


解决方案 1:

KeyError通常,如果您尝试获取字典中当前不存在的键的项目,Python 字典会抛出。defaultdict相反, 只会创建您尝试访问的任何项目(当然前提是它们尚不存在)。要创建这样的“默认”项目,它会调用您传递给构造函数的函数对象(更准确地说,它是一个任意的“可调用”对象,其中包括函数和类型对象)。对于第一个示例,使用 创建默认项目int(),它将返回整数对象0。对于第二个示例,使用 创建默认项目list(),它将返回一个新的空列表对象。

解决方案 2:

defaultdict意思是如果字典中没有找到某个键​​,那么不会KeyError抛出异常,而是创建一个新条目。这个新条目的类型由 defaultdict 的参数给出。

例如:

somedict = {}
print(somedict[3]) # KeyError

someddict = defaultdict(int)
print(someddict[3]) # print int(), thus 0

解决方案 3:

默认字典

“标准字典包含方法 setdefault(),用于检索值并在值不存在时建立默认值。相反,defaultdict在初始化容器时,让调用者预先指定默认值(要返回的值)。”

Doug Hellmann《Python 标准库示例》中定义

如何使用 defaultdict

导入 defaultdict

>>> from collections import defaultdict

初始化 defaultdict

通过传递来初始化它

可作为其第一个参数调用(强制)

>>> d_int = defaultdict(int)
>>> d_list = defaultdict(list)
>>> def foo():
...     return 'default value'
... 
>>> d_foo = defaultdict(foo)
>>> d_int
defaultdict(<type 'int'>, {})
>>> d_list
defaultdict(<type 'list'>, {})
>>> d_foo
defaultdict(<function foo at 0x7f34a0a69578>, {})

**kwargs作为其第二个参数(可选)

>>> d_int = defaultdict(int, a=10, b=12, c=13)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

或者

>>> kwargs = {'a':10,'b':12,'c':13}
>>> d_int = defaultdict(int, **kwargs)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

它是如何工作的

作为标准词典的子类,它可以执行所有相同的功能。

但如果传递了未知的键,它将返回默认值而不是错误。例如:

>>> d_int['a']
10
>>> d_int['d']
0
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12, 'd': 0})

如果你想更改默认值,请覆盖 default_factory:

>>> d_int.default_factory = lambda: 1
>>> d_int['e']
1
>>> d_int
defaultdict(<function <lambda> at 0x7f34a0a91578>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0})

或者

>>> def foo():
...     return 2
>>> d_int.default_factory = foo
>>> d_int['f']
2
>>> d_int
defaultdict(<function foo at 0x7f34a0a0a140>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0, 'f': 2})

问题中的例子

示例 1

由于 int 已作为 default_factory 传递,任何未知键将默认返回 0。

现在,当字符串在循环中传递时,它将增加 d 中这些字母的数量。

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> d.default_factory
<type 'int'>
>>> for k in s:
...     d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
>>> d
defaultdict(<type 'int'>, {'i': 4, 'p': 2, 's': 4, 'm': 1})

示例 2

由于列表已作为 default_factory 传递,任何未知(不存在)的键将默认返回 [ ](即列表)。

现在,当元组列表在循环中传递时,它将附加在 d[color] 中的值

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> d.default_factory
<type 'list'>
>>> for k, v in s:
...     d[k].append(v)
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
>>> d
defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})

解决方案 4:

字典是一种方便的方法来存储数据,以便以后通过名称(键)进行检索。键必须是唯一的、不可变的对象,并且通常是字符串。字典中的值可以是任何值。对于许多应用程序来说,值是简单类型,例如整数和字符串。

当字典中的值是集合(列表、字典等)时,情况会变得更有趣。在这种情况下,第一次使用给定键时必须初始化值(空列表或字典)。虽然手动完成相对容易,但 defaultdict 类型可以自动化和简化这些类型的操作。defaultdict 的工作原理与普通字典完全相同,但它使用不带参数的函数(“默认工厂”)进行初始化,并为不存在的键提供默认值。

defaultdict 永远不会引发 KeyError。任何不存在的键都会获得默认工厂返回的值。

from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')

ice_cream['Sarah'] = 'Chunky Monkey'
ice_cream['Abdul'] = 'Butter Pecan'

print(ice_cream['Sarah'])
>>>Chunky Monkey

print(ice_cream['Joe'])
>>>Vanilla

下面是另一个关于如何使用 defaultdict 来降低复杂性的例子

from collections import defaultdict
# Time complexity O(n^2)
def delete_nth_naive(array, n):
    ans = []
    for num in array:
        if ans.count(num) < n:
            ans.append(num)
    return ans

# Time Complexity O(n), using hash tables.
def delete_nth(array,n):
    result = []
    counts = defaultdict(int)

    for i in array:
        if counts[i] < n:
            result.append(i)
            counts[i] += 1
    return result


x = [1,2,3,1,2,1,2,3]
print(delete_nth(x, n=2))
print(delete_nth_naive(x, n=2))

总之,每当您需要一本字典,并且每个元素的值都应该以默认值开头时,请使用 defaultdict。

解决方案 5:

这里有关于 defaultdicts 的很好的解释:http ://ludovf.net/blog/python-collections-defaultdict/

基本上,参数intlist是您传递的函数。请记住,Python 接受函数名称作为参数。int默认返回 0,list在使用括号调用时返回空列表。

在普通字典中,如果在您的示例中我尝试调用d[a],我将收到错误 (KeyError),因为只有键 m、s、i 和 p 存在,而键 a 尚未初始化。但是在 defaultdict 中,它以函数名称作为参数,当您尝试使用尚未初始化的键时,它只会调用您传入的函数并将其返回值分配为新键的值。

解决方案 6:

在每次调用中,使用而不是defaultdict可以轻松模仿的行为。dict.setdefault`d[key]`

换句话说,代码:

from collections import defaultdict

d = defaultdict(list)

print(d['key'])                        # empty list []
d['key'].append(1)                     # adding constant 1 to the list
print(d['key'])                        # list containing the constant [1]

相当于:

d = dict()

print(d.setdefault('key', list()))     # empty list []
d.setdefault('key', list()).append(1)  # adding constant 1 to the list
print(d.setdefault('key', list()))     # list containing the constant [1]

唯一的区别是,使用时defaultdict,列表构造函数仅被调用一次,而使用dict.setdefault列表构造函数则被调用更频繁(但如果确实需要,可以重写代码以避免这种情况)。

有些人可能会认为这是出于性能方面的考虑,但这个话题是个雷区。 例如,这篇文章表明使用 defaultdict 不会带来很大的性能提升。

在我看来,defaultdict 是一个给代码带来更多困惑而不是好处的集合。对我来说毫无用处,但其他人可能不这么认为。

解决方案 7:

由于问题是关于“它是如何工作的”,一些读者可能希望看到更多细节。具体来说,所讨论的方法就是方法__missing__(key)。请参阅:https ://docs.python.org/2/library/collections.html#defaultdict-objects 。

__missing__(key)更具体地说,这个答案展示了如何以实用的方式
利用: https://stackoverflow.com/a/17956989/1593924

为了阐明“可调用”的含义,这里有一个交互式会话(来自 2.7.6 但也应该在 v3 中工作):

>>> x = int
>>> x
<type 'int'>
>>> y = int(5)
>>> y
5
>>> z = x(5)
>>> z
5

>>> from collections import defaultdict
>>> dd = defaultdict(int)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd = defaultdict(x)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd['a']
0
>>> dd
defaultdict(<type 'int'>, {'a': 0})

这是 defaultdict 最典型的用法(除了无意义地使用 x 变量)。您可以使用 0 作为显式默认值执行相同的操作,但不能使用简单值:

>>> dd2 = defaultdict(0)

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    dd2 = defaultdict(0)
TypeError: first argument must be callable

相反,下面的方法可以工作,因为它传递了一个简单的函数(它动态创建一个不带参数并且始终返回 0 的无名函数):

>>> dd2 = defaultdict(lambda: 0)
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {})
>>> dd2['a']
0
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {'a': 0})
>>> 

并具有不同的默认值:

>>> dd3 = defaultdict(lambda: 1)
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {})
>>> dd3['a']
1
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {'a': 1})
>>> 

解决方案 8:

我自己的 2¢: 你也可以将 defaultdict 子类化:

class MyDict(defaultdict):
    def __missing__(self, key):
        value = [None, None]
        self[key] = value
        return value

这对于非常复杂的情况非常有用。

解决方案 9:

嗯,defaultdict 在以下情况下也会引发 keyerror:

from collections import defaultdict
d = defaultdict()
print(d[3]) #raises keyerror

永远记得给 defaultdict 提供参数,例如

d = defaultdict(int)

解决方案 10:

defaultdict 工具是 Python 集合类中的一个容器。它与通常的字典 (dict) 容器类似,但有一个区别:值字段的数据类型是在初始化时指定的。

例如:

from collections import defaultdict

d = defaultdict(list)

d['python'].append("awesome")

d['something-else'].append("not relevant")

d['python'].append("language")

for i in d.items():

    print i

这将打印:

('python', ['awesome', 'language'])
('something-else', ['not relevant'])

解决方案 11:

简而言之:

defaultdict(int)- 参数 int 表示值将为 int 类型。

defaultdict(list)- 参数列表表示值将是列表类型。

解决方案 12:

我认为它最好用来代替 switch case 语句。想象一下,如果我们有如下 switch case 语句:

option = 1

switch(option) {
    case 1: print '1st option'
    case 2: print '2nd option'
    case 3: print '3rd option'
    default: return 'No such option'
}

python 中没有switch可用的 case 语句。我们可以通过使用 来实现相同的效果defaultdict

from collections import defaultdict

def default_value(): return "Default Value"
dd = defaultdict(default_value)

dd[1] = '1st option'
dd[2] = '2nd option'
dd[3] = '3rd option'

print(dd[4])    
print(dd[5])    
print(dd[3])

它打印:

Default Value
Default Value
3rd option

上面的代码片段中dd没有键 4 或 5,因此它会打印出我们在辅助函数中配置的默认值。这比原始字典好得多,原始字典中KeyError如果不存在键,则会抛出一个。由此可见,它defaultdict更像是一个 switch case 语句,我们可以避免复杂的if-elif-elif-else块。

这个网站上还有一个给我留下深刻印象的好例子:

>>> from collections import defaultdict
>>> food_list = 'spam spam spam spam spam spam eggs spam'.split()
>>> food_count = defaultdict(int) # default value of int is 0
>>> for food in food_list:
...     food_count[food] += 1 # increment element's value by 1
...
defaultdict(<type 'int'>, {'eggs': 1, 'spam': 7})
>>>

如果我们尝试访问除 之外的任何项目eggsspam我们将得到 0 的计数。

解决方案 13:

如果没有defaultdict,您可能可以为看不见的键分配新值,但无法修改它。例如:

import collections
d = collections.defaultdict(int)
for i in range(10):
  d[i] += i
print(d)
# Output: defaultdict(<class 'int'>, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9})

import collections
d = {}
for i in range(10):
  d[i] += i
print(d)
# Output: Traceback (most recent call last): File "python", line 4, in <module> KeyError: 0

解决方案 14:

标准字典包含方法 setdefault(),用于检索值并在值不存在时建立默认值。相比之下,defaultdict 允许调用者在初始化容器时预先指定默认值。

import collections

def default_factory():
    return 'default value'

d = collections.defaultdict(default_factory, foo='bar')
print 'd:', d
print 'foo =>', d['foo']
print 'bar =>', d['bar']

只要所有键都具有相同的默认值,这种方法就很有效。如果默认值是用于聚合或累积值的类型(例如列表、集合甚至 int),这种方法就特别有用。标准库文档中包含了几个以这种方式使用 defaultdict 的示例。

$ python collections_defaultdict.py

d: defaultdict(<function default_factory at 0x100468c80>, {'foo': 'bar'})
foo => bar
bar => default value

解决方案 15:

#dictinary and defaultdict

normaldictionary=dict()
print(type(normaldictionary))
#print(normaldictionary["keynotexisit"])
#Above normal dictionary give an error as key not present

from collections import defaultdict
defaultdict1=defaultdict()
print(type(defaultdict1))
#print(defaultdict1['keynotexisit'])
######################################

from collections import defaultdict
default2=defaultdict(int)
print(default2['keynotexist'])

https://msatutorpy.medium.com/ Different- Between-dictionary-and-defaultdictionary-cb215f682971

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1041  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   34  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   31  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   23  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   26  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用