我已经阅读了python docs中的示例,但仍然无法弄清楚这个方法的含义。有人可以帮忙吗?以下是python docs的两个例子
>>> from collections import defaultdict
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
... d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
和
>>> 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])]
参数int
和list
是针对什么的?
答案 0 :(得分:443)
答案 1 :(得分:178)
答案 2 :(得分:79)
"标准字典包括用于检索值的方法setdefault(),如果该值不存在则建立默认值。相比之下,defaultdict
允许调用者在初始化容器时预先指定默认值(要返回的值)。"
>>> from collections import defaultdict
通过传递
初始化它callable作为第一个参数(强制性)
>>> 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]})
答案 3 :(得分:18)
这里有一个很好的解释:http://ludovf.net/blog/python-collections-defaultdict/
基本上,参数 int 和 list 是您传递的函数。请记住,Python接受函数名作为参数。 int 默认返回0, list 在使用括号调用时返回空列表。
在普通词典中,如果在你的例子中我尝试调用d[a]
,我将得到一个错误(KeyError),因为只有键m,s,i和p存在且键a尚未初始化。但是在defaultdict中,它将函数名称作为参数,当您尝试使用尚未初始化的键时,它只是调用您传入的函数并将其返回值指定为新键的值。
答案 4 :(得分:9)
字典是存储数据以便以后通过名称(密钥)检索的便捷方式。键必须是唯一的,不可变的对象,通常是字符串。字典中的值可以是任何值。对于许多应用程序,值是简单类型,如整数和字符串。
当字典中的值是集合(列表,字符串等)时,它会变得更有趣。在这种情况下,必须在第一次使用给定键时初始化值(空列表或字典)。虽然手动操作相对容易,但defaultdict类型可以自动化并简化这些操作。 defaultdict的工作原理与普通dict完全相同,但是它使用一个不带参数的函数(“default factory”)进行初始化,并为不存在的键提供默认值。
defaultdict永远不会引发KeyError。任何不存在的密钥都会获得默认工厂返回的值。
from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')
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
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 :(得分:6)
我自己的2¢:你也可以继承defaultdict:
class MyDict(defaultdict):
def __missing__(self, key):
value = [None, None]
self[key] = value
return value
对于非常复杂的案件,这可能会派上用场。
答案 6 :(得分:5)
由于问题是关于“如何运作”,一些读者可能希望看到更多的细节。具体而言,所讨论的方法是__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})
>>>
答案 7 :(得分:2)
如果没有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
答案 8 :(得分:2)
在每次通话中,可以使用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
则多次调用列表构造函数(但是如果发生这种情况,可以重写代码以避免这种情况)确实需要)。
有些人可能会争论性能方面的考虑,但是这个话题是一个雷区。 This post shows there isn't a big performance gain in using defaultdict, for example.
IMO,defaultdict是一个集合,它给代码增加的混乱多于好处。对我没用,但其他人可能会有所不同。
答案 9 :(得分:1)
我认为它最好用来代替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
个案例语句。我们可以使用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
块。
从this site给我留下深刻印象的另一个好例子是:
>>> 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})
>>>
如果我们尝试访问eggs
和spam
以外的任何项目,我们将获得0的计数。
答案 10 :(得分:1)
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 :(得分:1)
好吧,在以下情况下,defaultdict也会引发键盘错误:
from collections import defaultdict
d = defaultdict()
print(d[3]) #raises keyerror
始终记住像defaultdict(int)一样为defaultdict提供参数。
答案 12 :(得分:0)
标准字典包括用于检索值的方法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']
只要所有键都具有相同的默认值,这种方法就可以正常工作。如果默认值是用于聚合或累积值的类型(例如list,set或甚至int),则它尤其有用。标准库文档包括几个使用defaultdict的例子。
$ python collections_defaultdict.py
d: defaultdict(<function default_factory at 0x100468c80>, {'foo': 'bar'})
foo => bar
bar => default value
答案 13 :(得分:0)
简而言之:
defaultdict(int)
-参数int表示值将为int类型。
defaultdict(list)
-参数列表指示值将为列表类型。
答案 14 :(得分:0)
#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
答案 15 :(得分:-6)
文档和解释几乎是不言自明的:
http://docs.python.org/library/collections.html#collections.defaultdict
作为参数传递的类型函数(int / str等)用于初始化任何给定键的默认值,其中键不存在于dict中。