这个问题是关于基于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用于属性的搜索顺序如下:
__setattr__
和raise AttributeError
- 数据描述符,如属性
- 来自对象
的实例变量__getattribute__
- 非数据描述符(如方法)和其他类变量
- 醇>
__setattr__
由于
__dict__
排在第一位,如果您有一个,则需要将其设为智能,除非希望它处理您班级的所有属性设置。它可以通过两种方式实现智能化。一个。使其仅处理特定的设置属性,或
湾使它处理除一些属性之外的所有属性。
对于您不希望它处理的那些,请致电
__getattr__
。
相关问题:
答案 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__
调用的 - 但感觉非常毛茸茸。