Создание словарей с предопределенными ключами - PullRequest
3 голосов
/ 04 мая 2009

Есть ли в python способ создать класс, который обрабатывается как словарь, но имеет предварительно определенные ключи при создании нового экземпляра?

Ответы [ 5 ]

9 голосов
/ 04 мая 2009

Вы также можете иметь подкласс dict, ограничивающий ключи предопределенным списком, переопределяя __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
8 голосов
/ 04 мая 2009

Вы можете легко расширить любой встроенный тип. Вот как бы вы сделали это с помощью dict:

>>> 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, в которой говорится об этом, но очень популярная книга Dive Into Python (доступна бесплатно онлайн) содержит несколько примеров по выполнению это.

3 голосов
/ 04 мая 2009

Да, в Python dict - это класс, поэтому вы можете создать его подкласс:

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

Здесь вы переопределяете метод dict __init__() (метод, который вызывается при создании экземпляра класса). Внутри __init__ вы сначала вызываете метод __init__() supercalss, который является обычной практикой, когда вы хотите расширить функциональность базового класса. Затем вы обновляете новый экземпляр SubDictionary своими исходными данными.

    subDict = SubDict()
    print subDict    # prints {'foo': 'bar', 'baz': 'spam'}
1 голос
/ 04 мая 2009

Я не уверен, что это то, что вы ищете, но когда я прочитал ваше сообщение, я сразу подумал, что вы ищете для динамического создания ключей для подсчета упражнений.

В отличие от 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 голосов
/ 04 мая 2009

Просто создайте подкласс dict и добавьте ключи в методе init .

class MyClass(dict)

def __init__(self):
    """Creates a new dict with default values""""

    self['key1'] = 'value1'

Помните, однако, что в python любой класс, который «действует как dict», обычно рассматривается как один, поэтому вам не нужно слишком беспокоиться о том, что он является подклассом, вместо этого вы можете реализовать методы dict, хотя Вышеупомянутый подход, вероятно, более полезен для вас:).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...