2017-01-07 2 views
7

私はコード全体で異なる単位で一般的に使用される値を持っています。例えば。バッファサイズをBYTES数で表しますが、多くの場所でKBまたはMBとしてサイズを参照しています(これは実際の使用例ではありません)。pythonのint値にプロパティを追加する

優雅さと使いやすさを考慮して、さまざまな場所で必要とされるため、明示的なコンバージョン(例:size/1024、またはb_to_mb(size))は避けたいと考えています。

私は、変換を容易にするプロパティ(x.kbまたはx.mb)でこれを実現できると考えていました。また、呼び出し元に格納されている実際の値の単位を知らないようにします。

私のコードは次のようになります。

class BufferSize(int): 
    @property 
    def b(self): 
     return int(self) 
    @property 
    def kb(self): 
     return self.b/1024 
    @property 
    def mb(self): 
     return self.kb/1024 

私は算術演算子を使用するまでは、動作します:

s = BufferSize(500000) 
s.kb 
=> 488.28125 # ok 
s.mb 
=> 0.476837158203125 # ok 
type(s + BufferSize(0)) 
=> int # type lost... 

は、タイプを保存する算術演算を確実にする方法はありますか?つまり、それぞれのすべてを上書きする以外のことですか?

元の問題を解決するには、別の方法がありますか?

+0

誤っキロバイトか何かの量にたBufferSizeを追加しないので、私は、int型をラップする代わりにint型から継承するお勧めします。算術演算子については、それらを個別に定義する必要があります。それほど意味のあるものはありません。それらのすべてを定義する必要はありません。 – user2357112

+3

一般的なユニットの操作については[Pint](https://pint.readthedocs.io/en/0.7.2/)を参照してください。 –

+1

@PeterWood Pintはこの問題のための絶対的なツールです。ありがとう。 – shx2

答えて

2

まあ、それはそんなに、intのマジックメソッドの結果キャストラップ/として再実装されていません少なくともこれらint sを返しますその...すべて、それらの、残念ながら。それをやや早めにするためにデコレータやメタクラスを使うことができないのであれば驚くべきことです。

class BufferSize(int): 
    @property 
    def b(self): 
     return int(self) 
    @property 
    def kb(self): 
     return self.b/1024 
    @property 
    def mb(self): 
     return self.kb/1024 

    def __add__(self, *args, **kwds): 
     return BufferSize(super(BufferSize, self).__add__(*args, **kwds)) 

v = BufferSize(1) + BufferSize(2) 

print v, type(v) 

出力:

3 <class '__main__.BufferSize'> 

また、私は自分自身をintに直接プロパティを追加することを考えましたが、簡単なテストはそれを除外。

>>> int.b = "b" 

出力:

can't set attributes of built-in/extension type 'int' 
関連する問題