2009-05-29 3 views
2

__getitem__をサポートするクラスを定義したいが、繰り返しはできない。例えば :Pythonで__getitem__をサポートしていますが、繰り返しはできません。

class B: 
    def __getitem__(self, k): 
     return k 

cb = B() 

for x in cb: 
    print x 

は私が失敗するfor x in cb:を強制的にクラスBに何を追加することができますか?

+0

はちょうどこのを求め、それに答えるには、場合に他の誰かがこれを行う方法を知っている必要があります。 – grieve

+3

好奇心の高まりから、なぜ* getitemへのアクセスを許可したいが、iterableにしたくないのですか?あなたのユースケースは何でしたか? –

+1

私は辞書のように振る舞いますが、継承しないクラスを持っています。したがって、私は__getitem__を定義しています。誰かが繰り返し処理しようとすると、整数で__getitem__を呼び出そうとするのではなく、エラーになります。私はこの特定のクラスを実装する方法を選択したわけではありませんが、私の決定は無効になっています。 – grieve

答えて

14

を私は思います普通の例外ではなくTypeErrorを発生させるのが少し良い解決策になります(これは通常、反復可能でないクラスで普通起こることです)。

テスト:

>>> iter(A()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'A' object is not iterable 
>>> iter(B()) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "iter.py", line 9, in __iter__ 
    % self.__class__.__name__) 
TypeError: 'B' object is not iterable 
+0

+1(アプローチの全体的な良さ)もあります。 –

+1

悲しいことに、isinstance(a、collections.Iterable)はTrueを返します。 – UncleZeiv

2

このquestionへの回答から、私たちは単にBを定義し、それが存在する場合__iter__は__getitem__前に呼び出されることがわかります。そして、

class B: 
    def __getitem__(self, k): 
     return k 

    def __iter__(self): 
     raise Exception("This class is not iterable") 

cb = B() 
for x in cb: # this will throw an exception when __iter__ is called. 
    print x 
+0

これ以上のpythonic答えがあれば、私はそれを喜んで受け入れます。 – grieve

+2

あなたはクラス名を適切に大文字にしました。新しいスタイルのクラスを適切に使用するためには、より平凡な数字の – SilentGhost

関連する問題