19

私は、いくつかのマシンがすべて同じバージョンのさまざまなクラスを持っているという仮定の下で通信する分散コンピューティングを行っています。したがって、これらのクラスを不変にするのは良い設計のようです。悪意のあるユーザーを阻止しなければならないという意味ではなく、誤って変更されることがないように不変であるだけです。

どうすればいいですか?たとえば、定義後にそれを使用するクラスを不変にするメタクラスをどのように実装しますか?

>>> class A(object):
...     __metaclass__ = ImmutableMetaclass
>>> A.something = SomethingElse # Don't want this
>>> a = A()
>>> a.something = Whatever # obviously, this is still perfectly fine.

クラスを受け取り、不変のクラスを返すデコレータ/関数など、代替メソッドも問題ありません。

4

3 に答える 3

7

使用の古いトリックが__slots__あなたに合わない場合、これ、またはそのいくつかの変形が行うことができます:__setattr__あなたのガードとなるようにあなたのメタクラスのメソッドを書くだけです。この例では、新しい属性が割り当てられるのを防ぎますが、既存の属性の変更は許可します。

def immutable_meta(name, bases, dct):
    class Meta(type):
        def __init__(cls, name, bases, dct):
            type.__setattr__(cls,"attr",set(dct.keys()))
            type.__init__(cls, name, bases, dct)

        def __setattr__(cls, attr, value):
            if attr not in cls.attr:
                raise AttributeError ("Cannot assign attributes to this class")
            return type.__setattr__(cls, attr, value)
    return Meta(name, bases, dct)


class A:
    __metaclass__ = immutable_meta
    b = "test"

a = A()
a.c = 10 # this works
A.c = 20 # raises valueError
于 2011-02-15T01:39:08.703 に答える
5

不変のクラスに時間を無駄にしないでください。

不変のオブジェクトを作成しようとするよりもはるかに簡単なことができます。

ここに5つの別々のテクニックがあります。あなたはそれらの中から選んで選ぶことができます。誰でも動作します。いくつかの組み合わせも機能します。

  1. ドキュメンテーション。実際、彼らはこれを忘れません。彼らに信用を与えなさい。

  2. 単体テスト。__setattr__例外として処理する単純なモックを使用して、アプリケーションオブジェクトをモックします。オブジェクトの状態を変更すると、単体テストで失敗します。それは簡単で、複雑なプログラミングを必要としません。

  3. オーバーライド__setattr__して、書き込みが試行されるたびに例外を発生させます。

  4. collections.namedtuple。それらは箱から出して不変です。

  5. collections.Mapping。不変ですが、機能させるにはいくつかのメソッドを実装する必要があります。

于 2011-02-14T21:49:03.023 に答える
1

他の人の作品を再利用してもかまわない場合:

http://packages.python.org/pysistence/

不変の永続的な(機能的には、デスクへの書き込みではない)データ構造。

そのまま使用しなくても、ソースコードからインスピレーションを得られるはずです。たとえば、それらのexpandoクラスは、コンストラクター内のオブジェクトを受け取り、その不変バージョンを返します。

于 2011-02-14T20:22:14.703 に答える