1

私は次のクラスを定義しています(その大部分は短縮されています)が、私の主な質問は、このクラスのオブジェクトが初期化された変数で定義されたら、これらの変数がクラスの外部から変更できないことを確認したいということです...このような試みが行われた場合は、AssertionError を発生させる必要があります。この例外を発生させるように定義されたsetattrメソッドがありますが、このメソッドを配置した後、このクラスで行ってきた以前のインスタンスとテストが完全に破棄され、この同じ AssertionError が常に発生します。このクラスのオブジェクトを作成しようとする試みが行われました...だから、ここに私のクラスの劇的に縮小されたバージョンがあります。

class Interval:
    compare_mode = None 

    def __init__(self, min, max):
        self.min = min 
        self.max = max 

    def min_max(min, max = None)-> 'Interval Object':
    .
    .
    .
    return Interval(min, max)

他のすべてのクラス メソッド...

def __setattr__(self, name, value):

    raise AssertionError('Objects in this class are immutable')

したがって、このクラスからミューティング オブジェクトをテストしようとすると、このクラスの残りのメソッドで以前のテストを破棄することに加えて、間違った例外が発生します。

p.min = 0;  raised wrong exception(NameError)
p.max = 0;  raised wrong exception(NameError)
p.HeyImChangingYourMethodandThereIsNothingYouCanDoToStopME  raised wrong exception(NameError)
4

2 に答える 2

2

あなたの質問は理解するのが少し難しいです - ただし、 では__init__、次のようなことを行います。

self.max = 0

これ__setattr__により、その場で例外が発生します。

本当に不変性が必要な場合は、collections.namedtuple+の使用を検討でき__slots__ます。

class Interval(collections.namedtuple('IntervalBase', 'min,max')):
    __slots__ = ()
    def method1(self):
        print self.min
        print self.max

デモとして:

>>> class Interval(collections.namedtuple('IntervalBase', 'min,max')):
...     __slots__ = ()
...     def method1(self):
...         print self.min
...         print self.max
... 
>>> Interval(1,2)
IntervalBase(min=1, max=2)
>>> Interval(1,2).method1
<bound method Interval.method1 of IntervalBase(min=1, max=2)>
>>> Interval(1,2).method1()
1
2
>>> Interval(1,2).foo = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Interval' object has no attribute 'foo'

Intervalただし、サブクラスも使用しない限り、ユーザーは のサブクラスに属性を追加できることに注意してください__slots__...


また、通常、ユーザーがアドホック属性をインスタンスに追加しても気にしないでください。API が提供するメソッドのいずれも変更できない場合 ( を介して強制できますproperty)、すべての意図と目的のために、クラスは不変であり、不変性が提供する世界を開くことができます (__hash__たとえば、合理的に定義されています)。

于 2014-04-26T06:23:45.573 に答える
0

また、 で設定したや など__setattr__、オブジェクトが独自の属性を設定することもできなくなります。self.minself.max__init__

これを回避したい場合は__init__、オブジェクトが初期化されているかどうかを示すフラグを最後に設定し、__setattr__このフラグをチェックして、フラグが設定されている場合は設定を許可しないようにします。または、__init__直接変更して属性を設定しますself.__dict__(例: self.__dict__['min'] = min)。

初期化するこれらのプロパティがいくつかしかない場合は、propertyそれぞれにゲッターのみのプロパティを使用して定義する方が読みやすい場合があります。ただし、 を使用する場合とは異なり__setattr__、これによってユーザーが新しい属性をクラスに追加できなくなることはありません。

于 2014-04-26T06:25:00.503 に答える