Python字典如何设置默认键值?

21

有没有办法让defaultdict默认返回key?或者有一种等效行为的数据结构吗?即,在初始化字典d后,

>>> d['a'] = 1
>>> d['a']
1
>>> d['b']
'b'
>>> d['c']
'c'
我只见过默认字典(default dictionaries)使用不需要参数的函数,所以除了创建一个新类型的字典之外,我不确定是否有其他解决方案。

这是一个有点过于专业化的任务。我建议你考虑对“dict”对象/类型进行子类化。 - heltonbiker
我对此很感兴趣。你能否给个想法,你需要它做什么? - Ben Butler-Cole
4个回答

25

我会重写 dict__missing__ 方法:

>>> class MyDefaultDict(dict):
...     def __missing__(self, key):
...         self[key] = key
...         return key
...
>>> d = MyDefaultDict()
>>> d['joe']
'joe'
>>> d
{'joe': 'joe'}

2
除非我需要知道查询了哪些键,否则存储键并返回它们是否有特定原因?我看不出这样做的理由。 - Joachim Sauer
@JoachimSauer:通常情况下,如果 d['joe'] 没有引发 KeyError,那么 'joe' in d 的值应该为 True。如果我没有存储这个键,那么情况就不同了。 - pillmuncher
1
但是这个解决方案使得'joe' in d的求值为False除非你在此之前使用了d['joe']。因此,纯粹的“只读”访问更改了另一个只读访问的结果。我不确定这是否更好。 - Joachim Sauer
2
@JoachimSauer:你说得对,但是存储键与collections.defaultdict的工作方式一致。 - pillmuncher

7

编辑: 噢,我刚才意识到我文件中的代码最初来自于另一个stackoverflow答案!https://dev59.com/lHE85IYBdhLWcg3wKwOE#2912455,请投票支持那个答案。

以下是我使用的代码——它是一个defaultdict变体,将键作为参数传递给作为参数传递给init的默认值工厂函数:

class keybased_defaultdict(defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key)
        else:
            value = self[key] = self.default_factory(key)
            return value

这是您想要的用途:

>>> d = keybased_defaultdict(lambda x: x)
>>> d[1]
1
>>> d['a']
'a'

其他可能性:

>>> d = keybased_defaultdict(lambda x: len(x))
>>> d['a']
1
>>> d['abc']
3

2
我其实有点惊讶地重新发现defaultdict并不像这样工作... - user166390
@pst 我想从理论上讲,如果您在键和值中存储相同的信息,则默认行为理论上可能没有意义 - 您可能正在使用错误的数据类型。 话虽如此,我确实在我的工作程序中使用它。 - weronika

4
如果您不想子类化字典,可以尝试使用。
d.get('a', 'a')
d.get('b', 'b')
d.get('c', 'c')

我认为这种方法更加清晰,对于这个目的来说不那么神秘。

如果您是DRY(Don't Repeat Yourself)的狂热者,并且只有单个字符键,您可以这样做 :)

d.get(*'a'*2)
d.get(*'b'*2)
d.get(*'c'*2)

3

你可能需要编写一个继承(或类似于)defaultdict的类,并覆盖__getitem__方法。

注:此处指在IT技术中编程方面的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接