この質問は、に基づくオブジェクトの読み取り専用の問題と、スーパーがサブクラスsuper()
を制御できるかどうか/どのように制御する必要があるかについてです。__setattr__
環境:
属性を含むクラスのサブクラスであるすべてのクラスがgetattr が「set_」で始まるサブクラス化された関数を実行できないように、メタクラスまたは記述子を作成する方法はありますか?self.read_only = True
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
) では、システム拡張機能はメッセージが read_only=False
であるべきであることを宣言するのを忘れています。これはsuper
s __setattr__
to になりraise AttributeError
ます:
中心的な質問: 以下の例に示す使用法は、BaseMessage クラスに基づくすべてのクラスに一貫して適用するのに十分でしょうか?
私をメタプログラミングの初心者だと考えてください。したがって、私の例の誤解および/または拡張および修正の説明は最高です。私は階層を理解しています [1]が、継承プロセス中に python がカーテンの後ろで何をしているのかについての洞察はありません。
ありがとう...
[1]: ヒエラルキー
Python が属性に使用する検索順序は次のようになります。
__getattribute__
と__setattr__
- プロパティなどのデータ記述子
- オブジェクトのインスタンス変数
__dict__
- 非データ記述子 (メソッドなど) およびその他のクラス変数
__getattr__
が最初に並んでいるので
__setattr__
、クラスのすべての属性設定を処理したくない場合を除き、スマートにする必要があります。2 つの方法のいずれかでスマートにすることができます。を。特定のセット属性のみを処理するようにする、または、
b. 一部の属性セットを除くすべてを処理できるようにします。
処理したくないものについては、 を呼び出します
super().__setattr__
。
関連する質問: