允许super控制子类

时间:2016-03-13 12:17:54

标签: python-3.x inheritance setattr

这个问题是关于基于super()的对象的只读问题,以及if / how如何/应该控制子类上的__setattr__

上下文

有没有办法编写元类 descriptor ,以便所有类都是包含属性{{1}的类的子类}无法执行子类化函数,其中getattr以“set_”开头,但self.read_only = True可以在哪里?

我在考虑覆盖self.read_only = False

  

尝试进行属性分配时调用。这就是所谓的   而不是正常的机制(即存储实例中的值)   字典)。 name是属性名称,value是要的值   分配给它。

...是正确的方向,但我怀疑我对文件的解释是否正确。

示例:

系统设计师

预期

超级

object.__setattr__(self, name, value)
系统扩展程序制作的

Sub 对所有后果的理解有限:

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

示例评论

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 中,系统扩展器明确声明read_only为False,并且明知地知道添加函数MutableMessage的后果。

set_topic(下方)中,系统扩展程序忘记声明该邮件应为read_only = ImmutableMessage,这应导致False s super到{{ 1}}:

核心问题: 下面的示例中显示的用法是否足以一致地应用于基于BaseMessage类的所有类?

将我视为元编程的新手。因此,对我的例子的任何误解和/或扩展和纠正的解释将是至高无上的。我理解hierarchy [1]但是没有深入了解继承过程中幕后蟒蛇的作用。

...谢谢

[1]:层次结构

  

Python用于属性的搜索顺序如下:

     
      
  1. __setattr__raise AttributeError
  2.   
  3. 数据描述符,如属性
  4.   
  5. 来自对象__getattribute__
  6. 的实例变量   
  7. 非数据描述符(如方法)和其他类变量
  8.   
  9. __setattr__
  10.         

    由于__dict__排在第一位,如果您有一个,则需要将其设为智能,除非希望它处理您班级的所有属性设置。它可以通过两种方式实现智能化。

         

    一个。使其仅处理特定的设置属性,或

         

    湾使它处理除一些属性之外的所有属性。

         

    对于您不希望它处理的那些,请致电__getattr__

相关问题:

1 个答案:

答案 0 :(得分: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__
  • 最大的瑕疵是你必须创建子类为读写,这样你就可以在第一时间创建属性,然后将其标记为只读。我无法想出一种自动化的方法。
    • 您或许可以super.__init__拨打派生__init__中的最后一个电话 - 但这并不是很自然。
    • 或者,__setattr__可以走遍堆栈并发现它是否是从__init__调用的 - 但感觉非常毛茸茸。