允许 super 在子类上控制 __setattr__
Allow super to control __setattr__ on subclasses
这个问题是关于基于 super()
和 if/how super can/should control __setattr__
on sub[=104= 的对象的只读问题]es.
上下文:
有没有一种方法可以编写 meta class 或 descriptor 以便所有 [=作为包含属性 self.read_only = True
的 class 子class 的 104=]es 无法执行 getattr 以 "set_" 开头的子classed 函数,但是self.read_only = False
哪里可以?
我认为 object.__setattr__(self, name, value)
的覆盖:
Called when an attribute assignment is attempted. This is called
instead of the normal mechanism (i.e. store the value in the instance
dictionary). name is the attribute name, value is the value to be
assigned to it.
...是正确的方向,但我怀疑我对文档的解释是否正确。
示例:
超级 系统设计者的意图:
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 由 system-extender 制作,他对所有后果的理解有限:
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
(下)中,系统扩展程序忘记声明消息应该是 read_only=False
,这应该导致 super
s __setattr__
到 raise AttributeError
:
核心问题:
下面示例中所示的用法是否足以一致地应用于所有基于 BaseMessage class 的 classes?
认为我是元编程的新手。因此,对我的示例的任何误解的解释 and/or 扩展和更正将是至高无上的。我了解 hierarchy [1] 但不了解 python 在继承过程中在幕后做了什么。
谢谢...
[1]:层次结构
The search order that Python uses for attributes goes like this:
__getattribute__
and __setattr__
- Data descriptors, like property
- Instance variables from the object's
__dict__
- Non-Data descriptors (like methods) and other class variables
__getattr__
Since __setattr__
is first in line, if you have one you need to make it smart unless want it to handle all attribute setting for your class. It can be smart in either of two ways.
a. Make it handle a specific set attributes only, or,
b. make it handle all but some set of attributes.
For the ones you don't want it to handle, call super().__setattr__
.
相关问题:
- Class properties and setattr
- Python - Re-Implementing setattr with super
这有点管用:
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__
)。
- 显然 none 这将阻止有人考虑覆盖
__setattr__
。
- 最大的缺点是您必须将子类创建为可读写,以便您可以首先创建属性,然后将其标记为只读。我想不出一种方法来自动化。
- 您可能能够使
super.__init__
调用派生 __init__
中的最后一个调用 - 但这感觉不太自然。
- 或者,
__setattr__
可以遍历堆栈并发现它是否被从 __init__
调用——但这感觉很麻烦。
这个问题是关于基于 super()
和 if/how super can/should control __setattr__
on sub[=104= 的对象的只读问题]es.
上下文:
有没有一种方法可以编写 meta class 或 descriptor 以便所有 [=作为包含属性 self.read_only = True
的 class 子class 的 104=]es 无法执行 getattr 以 "set_" 开头的子classed 函数,但是self.read_only = False
哪里可以?
我认为 object.__setattr__(self, name, value)
的覆盖:
Called when an attribute assignment is attempted. This is called instead of the normal mechanism (i.e. store the value in the instance dictionary). name is the attribute name, value is the value to be assigned to it.
...是正确的方向,但我怀疑我对文档的解释是否正确。
示例:
超级 系统设计者的意图:
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 由 system-extender 制作,他对所有后果的理解有限:
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
(下)中,系统扩展程序忘记声明消息应该是 read_only=False
,这应该导致 super
s __setattr__
到 raise AttributeError
:
核心问题: 下面示例中所示的用法是否足以一致地应用于所有基于 BaseMessage class 的 classes?
认为我是元编程的新手。因此,对我的示例的任何误解的解释 and/or 扩展和更正将是至高无上的。我了解 hierarchy [1] 但不了解 python 在继承过程中在幕后做了什么。
谢谢...
[1]:层次结构
The search order that Python uses for attributes goes like this:
__getattribute__
and__setattr__
- Data descriptors, like property
- Instance variables from the object's
__dict__
- Non-Data descriptors (like methods) and other class variables
__getattr__
Since
__setattr__
is first in line, if you have one you need to make it smart unless want it to handle all attribute setting for your class. It can be smart in either of two ways.a. Make it handle a specific set attributes only, or,
b. make it handle all but some set of attributes.
For the ones you don't want it to handle, call
super().__setattr__
.
相关问题:
- Class properties and setattr
- Python - Re-Implementing setattr with super
这有点管用:
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__
)。 - 显然 none 这将阻止有人考虑覆盖
__setattr__
。 - 最大的缺点是您必须将子类创建为可读写,以便您可以首先创建属性,然后将其标记为只读。我想不出一种方法来自动化。
- 您可能能够使
super.__init__
调用派生__init__
中的最后一个调用 - 但这感觉不太自然。 - 或者,
__setattr__
可以遍历堆栈并发现它是否被从__init__
调用——但这感觉很麻烦。
- 您可能能够使