通过将 default_factory 作为命名参数传递来构造 defaultdict
Construct defaultdict by passing default_factory as named parameter
我发现 colletions.defaultdict
有一些奇怪的行为:
import collections
c1 = collections.defaultdict(str)
c1['new'] # Works!
c2 = collections.defaultdict(default_factory=str)
c2['new'] # Raises KeyError...
为什么会引发 c2
KeyError?
有时我喜欢命名参数,因为我认为它增加了可读性。
首先我想也许 python 不允许我通过命名传递参数并将我的 default_factory
参数放入 kwargs,所以我检查了:
def func(first, **kwargs):
print(first)
print(kwargs)
func(first='one', second='two')
这输出:
one
{'second': 'two'}
原来不是这样。
defaultdict
构造函数的 default_factory
参数只是位置参数,实际上没有名称。如果您尝试按名称传递它,那么您只是在传递一个完全不相关的关键字参数。由于 defaultdict
构造函数的关键字参数被解释为其初始内容,因此您的字典开始时只有一个键 "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
如果此函数的文档将位置参数命名为 default_factory
,那可能是对其 含义 的正确描述,但如果它会产生误导暗示可以将其作为关键字参数传递。
一些内置函数是这样的,因为在 CPython C 代码中定义位置参数非常容易。对于 defaultdict
,它是设计使然,允许字面上的 any 字符串键用作初始内容的一部分,恰好被命名的键没有例外default_factory
.
我发现 colletions.defaultdict
有一些奇怪的行为:
import collections
c1 = collections.defaultdict(str)
c1['new'] # Works!
c2 = collections.defaultdict(default_factory=str)
c2['new'] # Raises KeyError...
为什么会引发 c2
KeyError?
有时我喜欢命名参数,因为我认为它增加了可读性。
首先我想也许 python 不允许我通过命名传递参数并将我的 default_factory
参数放入 kwargs,所以我检查了:
def func(first, **kwargs):
print(first)
print(kwargs)
func(first='one', second='two')
这输出:
one
{'second': 'two'}
原来不是这样。
defaultdict
构造函数的 default_factory
参数只是位置参数,实际上没有名称。如果您尝试按名称传递它,那么您只是在传递一个完全不相关的关键字参数。由于 defaultdict
构造函数的关键字参数被解释为其初始内容,因此您的字典开始时只有一个键 "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
如果此函数的文档将位置参数命名为 default_factory
,那可能是对其 含义 的正确描述,但如果它会产生误导暗示可以将其作为关键字参数传递。
一些内置函数是这样的,因为在 CPython C 代码中定义位置参数非常容易。对于 defaultdict
,它是设计使然,允许字面上的 any 字符串键用作初始内容的一部分,恰好被命名的键没有例外default_factory
.