2009-12-09 1 views
1

Основная цель следующего модуля - предоставить своего рода «постоянную» семантику для некоторых имен.Переопределенный доступ к атрибуту не работает (как ожидалось)

class ConstantError(Exception): 

    def __init__(self, msg): 
      self._msg = msg 


class Constant(object): 

    def __init__(self, name): 
      self._name = name 

    def __get__(self, instance, owner): 
      return instance._content[self._name] 

    def __set__(self, instance, value): 
      raise ConstantError, 'Illegal use of constant' 


class Constants(object): 

    def __init__(self, content): 
      self._content = content 
      for k in self._content: 
        setattr(self, k, Constant(k)) 

num_const = Constants({ 
    'one': 1, 
    'two': 2 
}) 

При использовании:

>>> from const import * 
>>> dir(num_const) 
['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_content', 'one', 'two'] 

Так one и two есть, но доступ атрибут diappointing:

>>> num_const.one 
<const.Constant object at 0x7faef4871710> 
>>> 

Где я пустошь ожидать 1 в этом случае. Где я ошибаюсь?

ответ

3

Протокол Дескриптор работает только на атрибуты класса, а не на атрибуты экземпляров класса. См. How-To Guide for Descriptors

+0

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

+0

Я не знаю, почему именно. Проблемы производительности для доступа к атрибутам? Или что было бы трудно получить доступ к самому атрибуту (дескриптору), не вызвав его. – u0b34a0f6ae

0

Вы пропускаете ул() или метод Юникода() в константах.

Добавить:

def __unicode__(self): 
    return self._name 
+0

Спасибо за ваш комментарий. К сожалению, это не помогает достичь ожидаемого поведения, то есть: 'num_cons.one' будет искать' 'one'' в' num_const._content' и возвращать его значение. –

0

Я думаю, что python препятствует доступу классов к дескрипторному оборудованию, чтобы с ними можно было манипулировать. В противном случае манипулирование дескриптором может стать очень сложным без какой-либо «магической» функции, и если вы заметили, что python пытается сохранить доступную доступную языковую технику. Чтобы обойти это, я часто создавал класс на лету. Например, класс вы Константы могут быть объявлены следующим образом:

class Constants(object): 
    def __new__(cls, content): 
     class _Constants(object): 
      pass 
     constants = _Constants 
     constants._content = content 
     for k in constants._content: 
      setattr(_Constants, k, Constant(k)) 
     return constants 

, но на самом деле, для вас целей вы могли бы быть лучше, вместе с:

class Constants(object): 
    def __init__(self, content): 
     self._content = content 
    def __getattr__(self,key): 
     return self._content[key]