Как динамически создавать свойства в Python?

Предположим, что у меня есть класс:

class Alphabet(object):
     __init__(self):
         self.__dict = {'a': 1, 'b': 2, ... 'z': 26}

     @property
     def a(self):
         return self.__dict['a']

     @property
     def b(self):
         return self.__dict['b']

     ...

     @property
     def z(self)
         return self.__dict['z']

Это была бы долгая и громоздкая задача для определения, и она кажется крайне избыточной. Есть ли способ динамически создавать эти свойства? Я знаю, что вы можете динамически создавать атрибуты со встроенным setattr, но я хочу иметь контроль над доступом для чтения/записи/удаления (по этой причине я хочу использовать свойство). Спасибо!

Ответы

Ответ 1

Не используйте свойства, но реализуйте следующие методы:

  • __getattr__(self, name)
  • __setattr__(self, name, value)
  • __delattr__(self, name)

См. http://docs.python.org/reference/datamodel.html#customizing-attribute-access

Ваш метод __getattr__ может выглядеть следующим образом:

def __getattr__(self, name):
    try:
        return self.__dict[name]
    except KeyError:
        msg = "'{0}' object has no attribute '{1}'"
        raise AttributeError(msg.format(type(self).__name__, name))

Ответ 2

Не делай этого. Просто позвольте потребителям класса на __dict напрямую и доверяйте им, чтобы не испортить его. Помните, мы все согласны с взрослыми здесь!

Нед Батчелдер объясняет мне лучше, чем я могу:


Сохранить данные из ваших имен переменных

Вопрос напомнил мне о других, которые я видел при переполнении стека или в #python IRC-канал:

  • Как узнать, существует ли переменная?
  • Как использовать переменную как имя другой переменной?
  • Как использовать переменную как часть имени таблицы SQL?

Все, что у них общего, пытается преодолеть разрыв между два домена: данные в вашей программе и имена данных в вашем программа. Каждый раз, когда это происходит, это явный признак того, что вам нужно повышайте уровень в моделировании данных. Вместо 26 списков вам нужно один словарь. Вместо N таблиц вы должны иметь одну таблицу, с еще один столбец.