Блокировка пользовательского словаря - PullRequest
2 голосов
/ 11 августа 2009

Добрый день, питонцы,

Я хочу сделать пользовательский словарь с двумя основными функциями:

  1. Все ключи объявляются при создании
  2. Невозможно добавить новые ключи или изменить текущие (значения по-прежнему могут быть изменены)

Прямо сейчас код такой:

class pick(dict):
   """This will make delicious toffee when finished"""
   def __init__(self, *args):
       dict.__init__(self)
       for arg in args:
           self[arg] = None

Любая помощь очень ценится.

UPD:

Хотя решение - это то, что я искал, есть одна проблема:

Словарь

вызывает __setitem__ для добавления элементов при инициализации и, не найдя ключей, вызывает ошибку.

cupboard = pick('milk')  #raises error

upd1:

все решено, большое спасибо.

Ответы [ 3 ]

12 голосов
/ 11 августа 2009

Переопределите метод __setitem__ желаемым поведением, вызовите dict.__setitem__(self, key, value), чтобы изменить базовый словарь без прохождения базовой логики.

class ImmutableDict(dict):
    def __setitem__(self, key, value):
        if key not in self:
             raise KeyError("Immutable dict")
        dict.__setitem__(self, key, value)

d = ImmutableDict(foo=1, bar=2)
d['foo'] = 3
print(d)
d['baz'] = 4 # Raises error

Вам также нужно переопределить dict.update() и setdefault(), чтобы избежать добавления ключей. И возможно dict.__delitem__(), dict.clear(), dict.pop() и dict.popitem(), чтобы избежать удаления ключей.

2 голосов
/ 11 августа 2009

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

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

2 голосов
/ 11 августа 2009

Что-то вроде

class UniqueDict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)

    def __setitem__(self, name, value):
        if name not in self:
            raise KeyError("%s not present")
        dict.__setitem__(self, name, value)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...