通过将default_factory作为命名参数传递来构造defaultdict

mar*_*rsl 3 python defaultdict

我得到一些奇怪的行为colletions.defaultdict:

import collections

c1 = collections.defaultdict(str)
c1['new']  # Works!

c2 = collections.defaultdict(default_factory=str)
c2['new']  # Raises KeyError... 
Run Code Online (Sandbox Code Playgroud)

为什么会引发c2KeyError?

有时我喜欢命名参数,因为我认为它增加了可读性.

首先我想也许python不允许我通过命名传递参数并将我的default_factory参数放到kwargs,所以我检查:

def func(first, **kwargs):
    print(first)
    print(kwargs)

func(first='one', second='two')
Run Code Online (Sandbox Code Playgroud)

这输出:

one
{'second': 'two'}
Run Code Online (Sandbox Code Playgroud)

所以事实并非如此.

use*_*342 5

构造函数的default_factory参数defaultdict只是位置,并没有真正的名称.如果您尝试按名称传递它,则只是传递一个完全不相关的关键字参数.由于defaultdict构造函数的关键字参数被解释为其初始内容,因此您的dict开始具有单个键,"default_factory"其值为str类型对象.

要了解其工作原理,请想象一下这样的函数:

def func(*args, **kwds):
    (default_factory,) = args
    for k, v in kwds.items():
        print(k, v)  # do something with keys and values
Run Code Online (Sandbox Code Playgroud)

如果此函数的文档用于命名位置参数default_factory,那么它可能是对其含义的正确描述,但如果它暗示可以将其作为关键字参数传递,则会产生误导.

一些内置函数就是这样,因为在CPython C代码中定义仅位置参数非常容易.用defaultdict,它是由设计,以允许从字面上任何字符串键将被用作初始的内容的部分,而不必对恰好被命名为关键的异常default_factory.