2015-10-25 14 views
9
>>> non_iterable = 1 
>>> 5 in non_iterable 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
TypeError: 'int' object is not iterable 

>>> class also_non_iterable: 
...  def __contains__(self,thing): 
...   return True 

>>> 5 in also_non_iterable() 
True 
>>> isinstance(also_non_iterable(), Iterable) 
False 

inキーワードが本当に欲しいときに反復可能なオブジェクトを望むという主張は、__contains__を実装するオブジェクトですか?なぜ 'in'キーワードはiterableオブジェクトが必要だと主張していますか?

答えて

13

オブジェクトのクラスが__contains__を実装していない場合、inはオブジェクトを反復しようとし、それによって得られる値に等しい。

アン例ことを示すために -

>>> class C: 
...  def __iter__(self): 
...   return iter([1,2,3,4]) 
>>> 
>>> c = C() 
>>> 2 in c 
True 
>>> 5 in c 
False 

これは__contains__()メソッドを定義するユーザ定義のクラスについてthe documentation -

に説明され、x in yy.__contains__(x)が真である場合にのみ真です。 yを反復しながらx == zでいくつかの値zを生成した場合__contains__()を定義していないが、__iter__()を定義しないユーザ定義クラスについて

x in yは真です。反復処理中に例外が発生した場合、例外が発生したかのようになります。

+0

意味があります。私は、エラーメッセージが少し正確ではないと思います。 –

+2

必ずしもそうではありません。あなたが最初に含まれているとしようとした場合、失敗し、次に反復に落ちていた場合、次に反復ビットは例外がバブルアップするところです。したがって、メッセージングは​​回復不可能なエラーの点と一貫しています。 –

+0

そして、それはドキュメントでも言及されています。*反復中に例外が発生した場合、例外が発生したようです。 –

1

inの二つの異なる用途があります:コンテナが値を持っている場合

  • テストシーケンスを通じて
  • トラバース(例えば左引数が__contains__を実装)
  • (。例えば右引数は Iterableです)
+0

良い点。しかし、大きなリスト(ここでの緩い使用法)を反復することは非常に効率的ではありません。それとももっとセットなのか。メンバーシップのテストはシーケンストラバーサルと特権チェックとの違いとは違って扱われますか? –

3

inキーワードは何それが本当に望んでいることは__contains__を実装したオブジェクトであるとき、反復可能なオブジェクトをしたいと主張する理由はありますか?

x in thingおよびfor x in thingは非常に密接に関連している。 x in thingをサポートするほとんどのものは、thingを超えるforループがxに等しい要素を見つける場合にのみ、x in thingが真であるというルールに従います。特に、オブジェクトが反復をサポートしていて、__contains__ではない場合、Pythonは反復をinテストのフォールバックとして使用します。

__contains__というエラーメッセージが表示されることがありますが、これは現在のメッセージとほぼ同じです。__contains__は厳密には必要でないためです。コンテナが必要だと言えるかもしれませんが、何がコンテナとして数えられるのかはすぐに分かりません。たとえば、dictsはinをサポートしていますが、コンテナを呼び出すのは疑問です。現在のメッセージ(iterableを必要としている)は、他のオプションと同じくらい正確です。その利点は、実際のオブジェクトがinをサポートしているかどうかを判断するために、実際には "it it itable"が "it is a container"か "__contains__をサポートしています"

+0

彼らは関連しています、はい、しかしまだ2つの異なるものです。 'for x in also_non_iterable()'も 'TypeError'を送出します。それは別のエラーです。 元のエラーの代わりに、 'オブジェクトは反復可能でないか、コンテナではないと言うのは簡単です。 –

関連する問題