使用预定义键创建字典

4
在Python中,是否有一种方法可以创建一个类,该类被视为字典,但在创建新实例时具有预定义的键?
5个回答

12

你还可以通过覆盖__setitem__()方法,使字典子类将键限制为预定义列表。

>>> class LimitedDict(dict):
    _keys = "a b c".split()
    def __init__(self, valtype=int):
        for key in LimitedDict._keys:
            self[key] = valtype()
    def __setitem__(self, key, val):
        if key not in LimitedDict._keys:
            raise KeyError
        dict.__setitem__(self, key, val)


>>> limited = LimitedDict()
>>> limited['a']
0
>>> limited['a'] = 3
>>> limited['a']
3
>>> limited['z'] = 0

Traceback (most recent call last):
  File "<pyshell#61>", line 1, in <module>
    limited['z'] = 0
  File "<pyshell#56>", line 8, in __setitem__
    raise KeyError
KeyError
>>> len(limited)
3

这对我来说是一个完美的解决方案,谢谢!不过,你能解释一下为什么要在'_keys'属性前面加下划线字符吗? - mc.suchecki
1
回复较晚,但是前导下划线是非正式的符号,用于表示该成员是本地的(“受保护的”)。 - Ryan Ginstrom

10

你可以轻松地扩展任何内置类型。以下是如何使用字典进行扩展:

>>> class MyClass(dict):
...     def __init__(self, *args, **kwargs):
...             self['mykey'] = 'myvalue'
...             self['mykey2'] = 'myvalue2'
...
>>> x = MyClass()
>>> x['mykey']
'myvalue'
>>> x
{'mykey2': 'myvalue2', 'mykey': 'myvalue'}

我找不到讲解这个问题的 Python 文档,但非常受欢迎的书籍《Python 禅意花园》(可免费在线阅读)提供了一些示例


2
我认为你应该从https://dev59.com/REfRa4cB1Zd3GeqP83D8#818019添加对dict.__init__的调用(或者更好的方法是使用super用户)。 - Sverre Rabbelier
这就是我最初的写法(查看历史记录),但经过一些研究,显然在这种情况下不需要它。根据上面的“Dive Into Python”链接:“dict不像这样工作;它不是一个包装器,并且不需要显式初始化。” - 不过我很想了解更多细节,因为我的第一反应是在那里使用super调用。 - Paolo Bergantino
过去的情况是,你根本不能使用 init 来子类化类型;你必须要用 new 进行操作。也许这与此有关。 - John Fouhy

3

是的,在Python中dict是一个类,因此您可以对其进行子类化:

    class SubDict(dict):
        def __init__(self):
            dict.__init__(self)
            self.update({
                'foo': 'bar',
                'baz': 'spam',})

在这里,你覆盖了字典的__init__()方法(这是在类的实例创建时调用的方法)。在__init__内部,你首先调用超类的__init__()方法,这是一种常见的做法,当你想要扩展基类功能时。然后,你使用初始数据更新了SubDictionary的新实例。

    subDict = SubDict()
    print subDict    # prints {'foo': 'bar', 'baz': 'spam'}

1

我不确定这是否符合您的要求,但当我阅读您的帖子时,我立即想到您正在寻找动态生成计数练习密钥。

与 Perl 不同,它会默认为您执行此操作,


grep{$_{$_}++} qw/ a a b c c c /;
print map{$_."\t".$_{$_}."\n"} sort {$_{$b}$_{$a}} keys %_;

c   3
a   2
b   1

Python不会免费为您提供这个:


l = ["a","a","b","c","c","c"]
d = {}
for item in l:
    d[item] += 1

Traceback (most recent call last):
  File "./y.py", line 6, in 
    d[item] += 1
KeyError: 'a'

然而,defaultdict会为您完成这项工作,


from collections import defaultdict
from operator import itemgetter

l = ["a","a","b","c","c","c"]
d = defaultdict(int)
for item in l:
    d[item] += 1

dl = sorted(d.items(),key=itemgetter(1), reverse=True)
for item in dl:
    print item

('c', 3)
('a', 2)
('b', 1)

0

只需创建 dict 的子类并在 init 方法中添加键即可。

class MyClass(dict)
def __init__(self): """创建一个带有默认值的新字典"""
self['key1'] = 'value1'

请记住,在 Python 中,任何“像字典一样”的类通常都会被视为字典,因此您不必太担心它是子类,您可以实现 dict 方法,尽管上述方法可能对您更有用 :)


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