3

この質問は、に基づくオブジェクトの読み取り専用の問題と、スーパーがサブクラスsuper()を制御できるかどうか/どのように制御する必要があるかについてです。__setattr__

環境:

属性を含むクラスのサブクラスであるすべてのクラスがgetattr が「set_」で始まるサブクラス化された関数を実行できないように、メタクラスまたは記述子を作成する方法はありますか?self.read_only = Trueself.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であるべきであることを宣言するのを忘れています。これはsupers __setattr__to になりraise AttributeErrorます:

中心的な質問: 以下の例に示す使用法は、BaseMessage クラスに基づくすべてのクラスに一貫して適用するのに十分でしょうか?

私をメタプログラミングの初心者だと考えてください。したがって、私の例の誤解および/または拡張および修正の説明は最高です。私は階層を理解しています [1]が、継承プロセス中に python がカーテンの後ろで何をしているのかについての洞察はありません。

ありがとう...

[1]: ヒエラルキー

Python が属性に使用する検索順序は次のようになります。

  1. __getattribute____setattr__
  2. プロパティなどのデータ記述子
  3. オブジェクトのインスタンス変数__dict__
  4. 非データ記述子 (メソッドなど) およびその他のクラス変数
  5. __getattr__

が最初に並んでいるので__setattr__、クラスのすべての属性設定を処理したくない場合を除き、スマートにする必要があります。2 つの方法のいずれかでスマートにすることができます。

を。特定のセット属性のみを処理するようにする、または、

b. 一部の属性セットを除くすべてを処理できるようにします。

処理したくないものについては、 を呼び出しますsuper().__setattr__

関連する質問:

4

1 に答える 1