0

Mask次のような高速な ID チェックを使用できるようにしたい、やや複雑なデータ型があります。

seen = set()
m = Mask(...)
if m in seen:
    ...

これは、マスクがハッシュ可能であるため、不変であることを示唆しています。ただし、のバリアントを生成したいのですが、バリアントmロジックMaskをカプセル化する場所のようです。これは、私が達成したいことを示す最小限の例です。

class Mask(object):
    def __init__(self, seq):
        self.seq = seq
        self.hash = reduce(lambda x, y: x ^ y, self.seq)

    # __hash__ and __cmp__ satisfy the hashable contract §3.4.1)
    def __hash__(self):
        return self.hash

    def __cmp__(self, other):
        return cmp(self.seq, other.seq)

    def complement(self):
        # cannot modify self without violating immutability requirement
        # so return a new instance instead
        return Mask([-x for x in self.seq])

これは、すべてのハッシュ可能および不変のプロパティを満たします。特殊性は、事実上 Factory メソッドであるものを持っていることですcomplement。これは、目的の機能を実装するための合理的な方法ですか? SOに関する多くの関連する質問が達成しようとしているように、「悪意のある」変更から保護することにまったく興味がないことに注意してください。

この例は意図的に小さくしているため、seq のタプルを作成することで簡単に解決できます。私が実際に扱っているタイプは、そのような単純なキャストを行う余裕がありません。

4

3 に答える 3

2

はい、これが不変クラスの書き方です。そうでなければオブジェクトの状態を変更するメソッドは、あなたの言葉では、新しいインスタンスを作成する「ファクトリ」になります。

補数を計算する特定のケースでは、メソッドに名前を付けて次のよう__invert__に使用できることに注意してください。

inv_mask = ~mask

演算子の構文は、操作が同じ型の新しい値を返すというクライアント コードへの強力なシグナルです。

于 2012-06-01T14:15:41.617 に答える
1

Python は不変性を強制しません。にあるオブジェクトが変更されていないことを確認するのは、ユーザーの責任ですset。それ以外の場合は、Python でセットや辞書を使用するために不変性は必要ありません。

于 2012-06-01T14:29:02.990 に答える
1

不変型を使用する場合、すべての「バリエーション」メソッドは新しいオブジェクト/インスタンスを返す必要があるため、その意味でファクトリになります。

多くの言語では文字列を不変にしています (Python を含む)。したがって、すべての文字列操作は新しい文字列を返します。strB = strA.replace(...)

インスタンスをまったく変更できたとしても、それは不変ではありません。

編集:

読み直して、あなたはこれが妥当かどうか尋ねています。私はイエスと答えます。ロジックを別の場所に配置するのは適切ではありません。文字列の不変性で指摘したように、既存のものから新しいバリエーションを取得するのは一般的なパラダイムです。

于 2012-06-01T14:07:51.113 に答える