2012-04-20 13 views
0

クラスを派生させてlistからクラスを派生させ、いくつかのインスタンス属性を追加してハッシュ可能にしたいと考えています。それを行うには良い(早くてきれいな)方法は何ですか?リストサブクラスをハッシュ可能にする

UPDATE:

私は、ユースケースの長い説明を削除しました。私はまた、関連しているが別々の問題をdifferent questionに移しました。

+0

それはあなたが求めている正確に何を伝えるのは難しい:これは、1つの缶が__new__内部からの属性のインスタンスにアクセスする方法です。 –

+0

タプルを使用できないのはなぜですか?名前付きアトリビュートがある場合のみ、[namedtuple'](http://docs.python.org/py3k/library/collections.html#collections.namedtuple)があります。 – delnan

+0

'hash(tuple(self))'を使用できますか? – WolframH

答えて

1

このコードは問題ありません。あなたはリストのコピーを作っていますが、それは少し遅いかもしれません。

def __hash__(self): 
    return hash(tuple(self.list_attribute)) 

高速化したい場合は、いくつかのオプションがあります。タプルではなく、リストとして

    list_attribute
  • ストア(それが完全に構築された後)
  • INIT時に一度ハッシュを計算し、ハッシュ値を格納します。あなたのクラスは不変なので、ハッシュは決して変更されないので、これを行うことができます。
  • 独自のハッシュ関数を記述します。ここにはhash function for tupleがあります。同様のことをしてください。
+0

サブクラスの場合のみに焦点を絞るように質問を短縮したので、タプルのオプションは消えます( '__init__'では変更できないので)。'__init__ '時間での計算はすばらしいアイディアですが、この場合だけでなく、いつも*良いアイデアではないのでしょうか?それでも、もちろん3番目の選択肢よりも遅いでしょう。 – max

+0

これは、オブジェクトがハッシュされる回数によって異なります。大文字小文字が0の場合は、前もってやりたいとは思わない。一般的なケースが* many *の場合は、事前計算が最善です。 –

+0

ハッシュを格納することもメモリ、btwを無駄にします。 –

1

あなたはselftupleを適用することができます。selfを-ing

class State(list): 
    def __hash__(self): 
     return hash((self.some_attribute, tuple(self))) 

tupleは全体のハッシュ・プロセスの約半分の時間を要する:

from timeit import timeit 

setup = "from __main__ import State; s = State(range(1000)); s.some_attribute = 'foo'" 
stmt = "hash(s)" 
print(timeit(stmt=stmt, setup=setup, number=100000)) 

setup = "r = list(range(1000))" 
stmt = "tuple(r)" 
print(timeit(stmt=stmt, setup=setup, number=100000)) 

プリント

0.9382011891054844 
0.3911763069244216 
+0

ありがとうございます。それはあまりにも悪くはないようです。 – max

1

これは答えよりもコメントのほうが多いですが、コメントになるには時間がかかりすぎます。

class Data(tuple): 
    def __new__(klass, arg): 
     data_inst = tuple.__new__(klass, arg) 
     data_inst.min = min(data_inst) 
     data_inst.max = max(data_inst) 
     return data_inst 

>>> d = Data([1,2,3,4]) 
>>> d 
(1, 2, 3, 4) 
>>> d.min 
1 
>>> d.max 
4 
>>> d1 = Data([1,2,3,4,5,6]) 
>>> d1.max 
6 
>>> d.max 
4 
+0

しかし、これらはクラス属性であり、インスタンス属性ではありません。 'd1 = Data([1,2,3,4])'を試してみると、 'd1.min is d.min'はTrueと評価されます。インスタンス間でそれらを区切ることはできません。 – max

+0

私はそうは思わない、試してください –

+0

ああ、あなたは正しいです。私が悪いのは、同じ 'int'オブジェクトを再利用する小さな数字なので、Trueと評価されるだけです。ニート! *私は 'tuple .__ new__'を呼び出すまで中間計算を保存する必要がありますが、うまくいきます。 – max

関連する問題