2017-06-16 9 views
2

を私はクラスDifferentialExtension持っている:不変クラスは、ビルドアップ

class DifferentialExtension(object): 
    __slots__ = ('f', 'x', 'D', 'T') 
    def __init__(self, f=None, x=None): 
     /* 
     # some code that builds up list 'self.D' 
     */ 
     self.D = tuple(self.D) 
     return None 

を私は「不変」、すなわちオブジェクトがDifferentialExtensionを使用して作成したクラスは、(「D」属性を変更することが許されるべきではない作ることになっています__init__終了後)、これらの属性は新しいオブジェクトに割り当てられません。 Dlistである必要はありません。最後に返される場合はtupleとなります。

In [1]: DE = DifferentialExtension(log(x), x) 
In [2]: DE.D 
Out[2]: ((Poly(1, x, domain='ZZ'), Poly(1/x, t0, domain='ZZ(x)')) 
In [3]: DE.D = (1, 5, 5) # raises Error. 

答えて

1

このようなものはありますか?

class DifferentialExtension(object): 
    _frozen = set() 
    __slots__ = ('f', 'x', 'D', 'T') 
    def __init__(self, f=None, x=None): 
     self.D = 'something' 
     self.D = tuple(self.D) 
     self._frozen.add(id(self)) 

    def __setattr__(self, attr, value): 
     if id(self) in self._frozen: 
      raise TypeError('object is frozen') 
     object.__setattr__(self, attr, value) 

テスト

In [29]: a = DifferentialExtension('eh', 'oh') 

In [30]: a.D 
Out[30]: ('s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g') 

In [31]: a.D = 'something else' 
... 
TypeError: object is frozen 

編集。 は別の答えで述べたように、namedtupleはこれを行うための自然な方法ですが、工事中に、いくつかの計算を行っていることから、代替コンストラクタとしてクラスメソッドを使用します。 namedtuple

class DifferentialExtension(namedtuple('DifferentialExtension', 'f, x, D, T')): 
    @classmethod 
    def build_me(cls, f=None, x=None): 
     # a bunch of code that works on D and sets D and T (if you need T) 
     T = 'something T' 
     D = 'something' ##D = tuple(D) works 
     return cls(f, x, D, T) 

テスト:

In [41]: DE = DifferentialExtension.build_me(f='some f value', x='some x value') 

In [42]: DE.D 
Out[42]: 'something' 

In [43]: DE.D = 'some other thing' 
... 

AttributeError: can't set attribute 
3

一般に、Pythonでは、あなたのクラスを使用する人は誰でも悪質なことをしようとしていると仮定する必要があります。したがって彼本当にの値を変更したい場合D彼はおそらく良い理由があります。したがって、恐らく非pythonicなので、Dを変更することは不可能にしたくないでしょう。ただし、ユーザーが誤ってDを変更しないようにすることができます。

これが与える実行
class DifferentialExtension(object): 
    def __init__(self, f=None, x=None): 
     self._D = 'immutable value' 
     return None 

    @property 
    def D(self): 
     return self._D 

>>> d = DifferentialExtension() 
>>> d.D = 'mutate' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: can't set attribute 

ユーザー本当にが直接self._Dにアクセスすることによって、彼ができる、値を変更したい場合はそれが最善のように、読み取り専用のプロパティで行われますしかし、あなたは内部の、強調されていない変数の1つを乱しているので、彼は自分が何をしているのかを知っていると仮定しなければなりません。

1

不変オブジェクトの基礎としてnamedtupleを使用してください。あなたが望むなら、あなたのニーズに合うようにそれらを広げることができます。

from collections import namedtuple 

class DifferentialExtension(namedtuple('DifferentialExtension', 'f x')): 
    def another_method(self): 
     print self.x 

x = DifferentialExtension(1, 2) 

x.f = 2.2 
# AttributeError: can't set attribute 
関連する問題