2016-03-13 3 views
3

Этот вопрос касается проблемы только для чтения для объектов, которые основаны на super(), и если/как супер может/должен управлять __setattr__ на подклассах.Разрешить супер контролировать __setattr__ в подклассах

Контекст:

Есть ли способ, чтобы написать мету класса или descriptor таким образом, что все классы, которые являются подклассами класса, содержащего атрибут self.read_only = True не может выполнять подклассы функции, где GetAttr является начало с «set_», но где self.read_only = False может?

Я имею в виду, что переопределение object.__setattr__(self, name, value):

Вызывается, когда присвоение атрибута попытка. Это называется вместо обычного механизма (т. Е. Сохраняет значение в экземпляре словаря ). name - это имя атрибута, значение - это значение, которое должно быть присвоено ему .

... является правильным направлением, но я сомневаюсь, правильна ли моя интерпретация документации.

Пример:

Супер согласно предписанию системщиком:

class BaseMessage(object): 
    def __init__(self, sender, receiver, read_only=True): 
     self.sender = sender 
     self.receiver = receiver 
     self.read_only = read_only 

    def __setattr__(self, name, value): 
     if self.read_only: 
      raise AttributeError("Can't set attributes as message is read only.") 
     else: 
      # ? set attribute...(suggestion welcome) 

    def get_sender(self): # Is a "get" and not "set" call, so it should be callable disregarding self.read_only's value. 
     return self.sender 

    def get_receiver(self): 
     return self.receiver 

Sub сделанное системой-расширитель, который имеет ограниченное понимание всех последствий:

class MutableMessage(BaseMessage): 
    def __init__(self, sender, receiver, topic, read_only=False): 
     super().__init__(sender=sender, receiver=receiver, read_only=read_only) 
     self.topic = topic 

    # this call should be okay as super's property is read_only=False. 
    def set_topic_after_init(new_topic): 
     self.topic = topic 

class ImmutableMessage(BaseMessage): 
    def __init__(self, sender, receiver, topic): # read_only=True ! 
     super().__init__(sender=sender, receiver=receiver, read_only=read_only) 
     self.topic = topic 

    # this call should fail as super's property is read_only=True. 
    def set_topic_after_init(new_topic): 
     self.topic = topic 

Комментарий к примеру

В MutableMessage система расширитель прямо заявляет, что read_only является ложным и заведомо известно, что о последствиях добавления функции set_topic.

В ImmutableMessage (ниже), система-расширитель забывает объявить, что сообщение должно быть read_only = False, которые должны привести к super с __setattr__ к raise AttributeError:

Основной вопрос: Будет ли использование, как показано в приведенном ниже примере достаточно последовательно применять все классы, основанные на классе BaseMessage?

Думайте обо мне как новичок в метапрограмме. Поэтому объяснение любых недоразумений и/или расширение и исправление моего примера было бы верховным. Я понимаю hierarchy [1], но не знаю, что делает python за шторами во время процесса наследования.

Спасибо ...

[1]: Иерархия

Порядок поиска, Python использует для атрибутов выглядит следующим образом:

  1. __getattribute__ и __setattr__
  2. дескрипторы данных, как собственность
  3. Переменные от объекта __dict__
  4. Non-Data descrip TORs (например, методы) и другие переменные класса
  5. __getattr__

Поскольку __setattr__ является первым в очереди, если у вас есть тот, который вы должны сделать его умным, если не хотите, чтобы обрабатывать все атрибуты настройки для вашего класса. Он может быть умным одним из двух способов.

a. Заставить его обрабатывать только определенные атрибуты набора или, или

b. заставить обрабатывать все, кроме некоторого набора атрибутов.

Для тех, с которыми вы не хотите его обрабатывать, позвоните по телефону super().__setattr__.

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

ответ

0

Это своего рода работы:

class BaseMessage(object): 
    def __init__(self, sender, receiver, read_only=True): 
     self._sender = sender 
     self._receiver = receiver 
     self.read_only = read_only 

    def __setattr__(self, name, value): 
     # Have to use gettattr - read_only may not be defined yet. 
     if getattr(self,"read_only",False): 
      raise AttributeError("Can't set attributes as message is read only.") 
     else: 
      self.__dict__[name] = value 

    def get_sender(self): # Is a "get" and not "set" call, so it should be callable 
     return self._sender # disregarding self.read_only's value. 

    def get_receiver(self): 
     return self._receiver 


class ImmutableMessage(BaseMessage): 
    def __init__(self, sender, receiver, topic): # read_only=True ! 
     # Have to make it read-write to start with 
     super().__init__(sender=sender, receiver=receiver, read_only=False) 
     # ... so we can set the topic 
     self.topic = topic 
     # Now make it read-only 
     self.read_only = True 

    # this call should fail as super's property is read_only=True. 
    def set_topic_after_init(self,new_topic): 
     self.topic = new_topic 
  • Настройка атрибута проста (просто установите __dict__).
  • Очевидно, что ничто из этого не остановит кого-либо, рассматривающего переопределение __setattr__.
  • Самая большая бородавка заключается в том, что вы должны создать подкласс как чтение-запись, чтобы вы могли сначала создать атрибуты, а затем пометить его только для чтения. Я не могу придумать способ автоматизировать это.
    • Возможно, вы сможете позвонить в последний звонок в производном __init__ - но это не очень естественно.
    • В качестве альтернативы __setattr__ может ходить по стеклу и обнаруживать, вызвана ли она от __init__ - но это очень волосатое.

 Смежные вопросы

  • Нет связанных вопросов^_^