这个问题是关于基于对象的只读问题super()
以及是否/如何超级可以/应该控制__setattr__
子类。
语境:
有没有办法编写元类或描述符,使得作为包含该属性的类的子类的所有类都self.read_only = True
不能执行 getattr 以“set_”开头的子类函数,但是在哪里self.read_only = False
可以呢?
我认为覆盖object.__setattr__(self, name, value)
:
在尝试进行属性分配时调用。这被称为而不是正常机制(即将值存储在实例字典中)。name 是属性名称,value 是要分配给它的值。
...是正确的方向,但我怀疑我对文档的解释是否正确。
例子:
正如系统设计者所期望的那样:
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
示例注释
在MutableMessage
系统扩展程序中明确声明 read_only 是 False 并且知道添加函数的后果set_topic
。
在ImmutableMessage
(下)中,系统扩展程序忘记声明 message 应该是 read_only=False
这应该导致super
s __setattr__
to raise AttributeError
:
核心问题: 下面示例中所示的用法是否足以一致地应用于基于 BaseMessage 类的所有类?
认为我是元编程的新手。因此,对我的示例的任何误解和/或扩展和更正的解释将是至高无上的。我了解层次结构 [1],但不了解 python 在继承过程中在幕后做了什么。
谢谢...
[1]:层次结构
Python 用于属性的搜索顺序如下所示:
__getattribute__
和__setattr__
- 数据描述符,如属性
- 来自对象的实例变量
__dict__
- 非数据描述符(如方法)和其他类变量
__getattr__
因为
__setattr__
它是排在第一位的,如果你有一个,你需要让它变得聪明,除非希望它处理你班级的所有属性设置。它可以通过两种方式中的任何一种变得聪明。一个。使其仅处理特定的集合属性,或者,
湾。让它处理除某些属性之外的所有属性。
对于您不希望它处理的那些,请致电
super().__setattr__
.
相关问题: