【问题标题】:Populating a defaultdict at init time在初始化时填充默认字典
【发布时间】:2014-02-01 22:38:48
【问题描述】:

我怎样才能为 defaultdict 获得一个可调用工厂,以允许用理解填充它?我认为这可能是不可能的,但我想不出一个好的理由?

>>> def foo(*args):
...     # TODO
...
>>> from collections import defaultdict
>>> thing = foo(defaultdict, int)
>>> d = thing((i, i*i) for i in range(3))
>>> d[2]
# should return 4
>>> d[-1]
# should return 0

【问题讨论】:

  • 我不明白你在做什么。什么是thingfoo,为什么thing 应该返回0?
  • 澄清一下:thing((i, i*i) for i in range(3)) 应该返回一个defaultdict 实例。我将编辑问题以使其更清晰
  • 哦,好吧,-1 让我觉得这是一个列表,而不是缺失的索引。如果你想要一个可以做到这一点的default_factory,我不认为它可以做到,因为(来自文档)“默认工厂被称为 没有参数当键不存在时产生一个新值,仅在 getitem 中。"

标签: python list-comprehension defaultdict generator-expression


【解决方案1】:

default_factory 之后的任何defaultdict 参数都被视为dict 的参数:

>>> defaultdict(int, [(i, i*i) for i in range(5)])
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4, 3: 9, 4: 16})

只需将理解传递给defaultdict 并让它完成工作:

def defaultdict_factory_factory(default_factory):
    def defaultdict_factory(*args, **kwargs):
        return defaultdict(default_factory, *args, **kwargs)
    return defaultdict_factory

或者使用functools.partial:

def defaultdict_factory_factory(default_factory):
    return partial(defaultdict, default_factory)

【讨论】:

  • 非常好!这在文档 (docs.python.org/2/library/…) 中有说明,但在 help(defaultdict) 中没有说明(至少在我的 Python 2.7 安装中)
  • 是的,令人惊讶的是,defaultdict 的文档字符串中缺少。我想知道还有多少其他的小蟒蛇秘密隐藏在那里......
  • 如果 3.4b2 的文档字符串中仍然缺少此内容,则应有人提交错误报告。 (我假设defaultdict 受到争论诊所德比的影响,所以你不能只查看最新的 3.3 版本。)
  • 最新的后备箱里还是不见了,所以我提交了bugs.python.org/issue20250
  • 附带说明,OP 使用的是genexpr,您已将其转换为listcomp,没有明显的理由这样做。
【解决方案2】:

你只是在寻找defaultdict.update吗?

>>> from collections import defaultdict
>>> thing = defaultdict(int)
>>> thing.update((i, i*i) for i in range(3))
>>> thing
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4})

你可以把它放到一个函数中。

>>> def initdefaultdict(type_, *args, **kwargs):
...     d = defaultdict(type_)
...     d.update(*args, **kwargs)
...     return d
... 
>>> thing = initdefaultdict(int, ((i, i+10) for i in range(3)))
>>> thing
defaultdict(<type 'int'>, {0: 10, 1: 11, 2: 12})
>>> thing[3]
0

或者为了满足你原来的需求,返回一个函数:

>>> def defaultdictinitfactory(type_): # this is your "foo"
...     def createupdate(*args, **kwargs):
...             d = defaultdict(type_)
...             d.update(*args, **kwargs)
...             return d
...     return createupdate
... 
>>> f = defaultdictinitfactory(int) # f is your "thing"
>>> d = f((i, i*i) for i in range(3))
>>> d
defaultdict(<type 'int'>, {0: 0, 1: 1, 2: 4})
>>> 

【讨论】:

  • 我没想到。如果update 没有返回 None 它几乎可以工作!
猜你喜欢
  • 1970-01-01
  • 2014-12-29
  • 2012-11-29
  • 1970-01-01
  • 2020-02-08
  • 2013-02-28
  • 1970-01-01
  • 2017-11-21
  • 1970-01-01
相关资源
最近更新 更多