Вопрос по python – Как мне динамически создавать свойства в Python?

15

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

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, но я хочу иметь контроль над доступом для чтения / записи / удаления (по этой причине я хочу использовать свойство). Спасибо!

@ThiefMaster: я исправляюсь :) Joel Cornett
дела@property\ndef something() эквивалентноsomething = property(something), Что эквивалентно действию (в этом случае)self.setattr('a', property(lambda self: self.__dict['a'])) Joel Cornett
@JoelCornett: второе утверждение в вашем комментарии неверно, вам нужно установить его для класса, а не для экземпляра:paste.aeum.net/show/106, Причина этого в том, чтоhow descriptors work: The following methods only apply when an instance of the class containing the method (a so-called descriptor class) appears in an owner class (the descriptor must be in either the owner’s class dictionary or in the class dictionary for one of its parents). ThiefMaster♦

Ваш Ответ

2   ответа
0

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

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

Keep data out of your variable names

The question reminded me of others I've seen on Stack Overflow or in the #python IRC channel:

How do I see if a variable exists? How do I use a variable as the name of another variable? How do I use a variable as part of a SQL table name?

The thing all these have in common is trying to bridge the gap between two domains: the data in your program, and the names of data in your program. Any time this happens, it's a clear sign that you need to move up a level in your data modeling. Instead of 26 lists, you need one dictionary. Instead of N tables, you should have one table, with one more column in it.

Нед имеет хороший смысл, но здесь есть цель инкапсуляции. Это важно не только для предотвращения ошибок (которые могут совершать и взрослые по обоюдному согласию), но и для удобства. Внутренний код класса, вероятно, имеет веские основания рассматривать словарь как словарь, в то время как код клиента обрабатывает его как набор атрибутов.
Проблема с доступом__dict непосредственно это уродливо, особенно с искажением названия, которое будет вовлечено. Небольшой синтаксический сахар для клиентов иногда имеет большое значение, не говоря уже об уровне косвенности, который он обеспечивает, будет способствовать возможным будущим изменениям.
30

__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))
Спасибо! Очень просто и легко понять.
+1: также заботится о СУХОЙ проблеме.
Это прекрасно!

Похожие вопросы