dict和collections.defaultdict有什么区别?

Leg*_*end 21 python dictionary

我正在查看Peter Norvig 关于如何编写简单拼写检查器的代码.最初,他使用此代码将单词插入字典中.

def train(features):
    model = collections.defaultdict(lambda: 1)
    for f in features:
        model[f] += 1
    return model
Run Code Online (Sandbox Code Playgroud)

Python dict和这里使用的那个有什么区别?另外,是什么lambda?我在这里检查了API文档并且它说defaultdict实际上是从dict派生的,但是如何决定使用哪一个?

Don*_*ner 31

不同之处在于,defaultdict如果尚未设置该键,则将"默认"一个值.如果您没有使用a defaultdict,则必须检查该密钥是否存在,如果不存在,请将其设置为您想要的密钥.

lambda正在为默认值定义工厂.只要需要默认值,就会调用该函数.你可以假设有一个更复杂的默认函数.

Help on class defaultdict in module collections:

class defaultdict(__builtin__.dict)
 |  defaultdict(default_factory) --> dict with default factory
 |  
 |  The default factory is called without arguments to produce
 |  a new value when a key is not present, in __getitem__ only.
 |  A defaultdict compares equal to a dict with the same items.
 |  
Run Code Online (Sandbox Code Playgroud)

(来自help(type(collections.defaultdict())))

{}.setdefault本质上是相似的,但它取值而不是工厂函数.它用于设置值,如果它尚不存在......但这有点不同.


Man*_*noj 12

让我们深入研究Python字典和Pythondefaultdict()

Python 字典

Dict 是 Python 中可用的数据结构之一,它允许以键值对的形式存储数据。

例子:

d = {'a': 2, 'b': 5, 'c': 6}
Run Code Online (Sandbox Code Playgroud)

字典问题

字典可以很好地工作,除非您遇到缺少键的情况。假设您正在寻找字典中没有值的键值对 - 那么您可能会遇到问题KeyError。像这样的东西:

d = {'a': 2, 'b': 5, 'c': 6}
d['z']  # z is not present in dict so it will throw a error
Run Code Online (Sandbox Code Playgroud)

你会看到这样的东西:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
    d['z'] 
KeyError: 'z'
Run Code Online (Sandbox Code Playgroud)

上述问题的解决方案

为了解决上述问题,我们可以使用不同的方法:

使用内置函数

setdefault

如果key在字典中,则返回它的值。如果不是,则插入一个值为 的键default并返回defaultdefault默认为None

>>> d = {'a' :2, 'b': 5, 'c': 6}
>>> d.setdefault('z', 0)
0  # returns 0 
>>> print(d)  # add z to the dictionary
{'a': 2, 'b': 5, 'c': 6, 'z': 0}
Run Code Online (Sandbox Code Playgroud)

get

key如果键在字典中,则返回 的值,否则返回default。如果未给出默认值,则默认为None,因此此方法永远不会引发KeyError

>>> d = {'a': 2, 'b': 5, 'c': 6}
>>> d.get('z', 0)
0  # returns 0 
>>> print(d)  # Doesn't add z to the dictionary unlike setdefault
{'a': 2, 'b': 5, 'c': 6}
Run Code Online (Sandbox Code Playgroud)

以上2个方法就是解决我们问题的方法。它永远不会升高KeyError。除了上述2种方法之外,Python还有一个collections模块可以处理这个问题。让我们深入研究一下defaultdict集合模块:

defaultdict

defaultdict可以在Python的collections模块中找到。您可以使用它:

from collections import defaultdict

d = defaultdict(int)
Run Code Online (Sandbox Code Playgroud)

defaultdict构造函数将default_factory可调用的参数作为参数。例如,这可以是:

  • int:默认值为整数值0

  • str:默认为空字符串""

  • list:默认为空列表[]

代码:

from collections import defaultdict

d = defaultdict(list)
d['a']  # access a missing key and returns an empty list
d['b'] = 1 # add a key-value pair to dict
print(d)
Run Code Online (Sandbox Code Playgroud)

输出将是defaultdict(<class 'list'>, {'b': 1, 'a': []})

其作用与和方法defaultdict相同,那么什么时候使用它们呢?get()setdefault()

何时使用get()

如果您特别需要返回某个键值对,KeyError并且它不应该在字典中更新,那么这dict.get对您来说是正确的选择。它返回您指定的默认值,但不会修改字典。

何时使用setdefault()

如果您需要使用默认键值对修改原始字典 - 那么setdefault是正确的选择。

何时使用defaultdict

setdefault方法可以使用来实现defaultdict,但setdefault我们可以在 中立即执行,而不是每次都提供默认值defaultdict。还,setdefault还可以选择为键提供不同的默认值。根据用例,两者都有自己的优点。

当谈到效率时:

defaultdict>setdefault()get()

defaultdict比 2 倍快get()

您可以在此处查看结果。

  • 非常好的详细答案!一个问题是你给出的“defaultdict”示例。您创建一个“defaultdict(list)”,然后执行“d['b'] = 1”。这失去了使用 defaultdict 的意义。更惯用的用例是当我们想要将某些内容附加到列表中而不检查键是否已经存在时。所以我会将该示例更改为“d['b'].append(1)”并显示它变成一个列表“[1]” (2认同)

sak*_*esh 8

礼貌:- https://shirishweb.wordpress.com/2017/05/06/python-defaultdict-versus-dict-get/

使用普通字典

d={}
d['Apple']=50
d['Orange']=20
print(d['Apple'])
print(d['Grapes'])# This gives Key Error
Run Code Online (Sandbox Code Playgroud)

我们也可以通过在普通字典中使用默认值来避免这个 KeyError,让我们看看我们怎么做

d={}
d['Apple']=50
d['Orange']=20
print(d['Apple'])
print(d.get('Apple'))
print(d.get('Grapes',0)) # DEFAULTING
Run Code Online (Sandbox Code Playgroud)

使用默认字典

from collections import defaultdict
d = defaultdict(int) ## inside parenthesis we say what should be the default value.
d['Apple']=50
d['Orange']=20
print(d['Apple'])
print(d['Grapes']) ##? This gives Will not give error
Run Code Online (Sandbox Code Playgroud)

使用用户定义的函数来默认值

from collections import defaultdict
def mydefault():
        return 0

d = defaultdict(mydefault)
d['Apple']=50
d['Orange']=20
print(d['Apple'])
print(d['Grapes'])
Run Code Online (Sandbox Code Playgroud)

概括

  1. 正常字典中的默认情况视具体情况而定,而在 defaultdict 中,我们可以以一般方式提供默认值

  2. 通过 defaultdict 使用默认值的效率是使用普通 dict 进行默认值的两倍。您可以参考以下链接以更好地了解此性能测试 https://shirishweb.wordpress.com/2017/05/06/python-defaultdict-versus-dict-get/


Rob*_*aus 7

如果缺少某些有意义的默认值并且不想明确处理它们,请使用defaultdict.

defaultdict构造函数将函数作为参数,并使用该函数构造值.

lambda: 1
Run Code Online (Sandbox Code Playgroud)

与执行此操作的无参数函数f相同

def f():
 return 1
Run Code Online (Sandbox Code Playgroud)

我忘记了API以这种方式设计的原因,而不是将值作为参数.如果我设计了defaultdict接口,它会稍微复杂一点,缺失值创建函数会将缺少的键作为参数.

  • 我认为 `defaultdict` 的工厂函数没有参数的原因是它可以用于那些 `__init__()` 构造函数不需要任何参数的类型——比如 `int`、`list` 和 `dict `. 当然,您可以轻松地从 `defaultdict` 派生一个子类,其 `__missing__()` 方法 _does_ 将密钥传递给工厂函数。请参阅[是否有一种巧妙的方法将密钥传递给 defaultdict 的 default_factory?] 的答案(http://stackoverflow.com/questions/2912231/is-there-a-clever-way-to-pass-the-key- to-defaultdicts-default-factory)。 (2认同)