16

我正在尝试做类似的事情:

from   collections import defaultdict
import hashlib

def factory():
    key = 'aaa'
    return { 'key-md5' : hashlib.md5('%s' % (key)).hexdigest() }

a = defaultdict(factory)
print a['aaa']

(实际上,我需要访问工厂中的密钥的原因不是为了计算 an md5,而是出于其他原因;这只是一个示例)

如您所见,在工厂中我无法访问密钥:我只是在强迫它,这没有任何意义。

是否可以以defaultdict我可以在工厂访问密钥的方式使用?

4

3 回答 3

27

__missing__ofdefaultdict不会传递key给工厂函数。

如果default_factory不是None,则在不带参数的情况下调用它以为给定键提供默认值,该值将插入到键的字典中,并返回。

__missing__使用自定义方法制作自己的字典类。

>>> class MyDict(dict):
...     def __init__(self, factory):
...         self.factory = factory
...     def __missing__(self, key):
...         self[key] = self.factory(key)
...         return self[key]
... 
>>> d = MyDict(lambda x: -x)
>>> d[1]
-1
>>> d
{1: -1}
于 2013-10-16T09:03:53.567 回答
6

不幸的是,不是直接的,因为 defaultdict 指定 default_factory 必须在没有参数的情况下调用:

http://docs.python.org/2/library/collections.html#collections.defaultdict

但是可以使用 defaultdict 作为具有您想要的行为的基类:

class CustomDefaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory:
            dict.__setitem__(self, key, self.default_factory(key))
            return self[key]
        else:
            defaultdict.__missing__(self, key)

这对我有用:

>>> a = CustomDefaultdict(factory)
>>> a
defaultdict(<function factory at 0x7f0a70da11b8>, {})
>>> print a['aaa']
{'key-md5': '47bce5c74f589f4867dbd57e9ca9f808'}
>>> print a['bbb']
{'key-md5': '08f8e0260c64418510cefb2b06eee5cd'}
于 2013-10-16T09:21:31.050 回答
0

在几种情况下,我想要一个带有工厂密钥的 defaultdict,我发现一个lru_cache也解决了我的问题:

import functools

@functools.lru_cache(maxsize=None)
def use_func_as_dict(key='') # Or whatever type
    with open(key, 'r') as ifile:
        return ifile.readlines()

f1 = use_func_as_dict('test.txt')
f2 = use_func_as_dict('test2.txt')
# This will reuse the old value instead of re-reading the file
f3 = use_func_as_dict('test.txt')
assert f3 is f1

从理论上讲,这实际上更有意义,因为您追求的是输入的功能,而不是一致的虚拟后备。

于 2021-11-04T19:40:12.990 回答