2015-10-28 15 views
10

私は、Pythonを初めて使うユーザー向けに一連のテストケースを作成しています。私がテストで気づいた問題の1つは、偽陽性を得ることが可能であるということです。彼らは幸運を得て、正しい順序ですべての要素を与えることができたかもしれませんが、実際には順序付けられた構造を使用する必要があります。Pythonの構造に順序があるかどうかを確認する方法はありますか?

これまでのところ、これは私が思いつく最良の解決策です。

self.assertTrue(isinstance(result, Sequence) or 
       isinstance(result, GeneratorType) or 
       callable(getattr(result, '__reversed__', False))) 

しかし、私はGeneratorType自信を持って感じることはありません実際に注文した、またはこのテストは包括的であるとされます。これをテストするためのより良い方法があるはずです。構造体に順序があることをどのようにテストしますか?

+1

あなたが何をしているのかを理解することはかなり難しいです。例を挙げてください。構造によって、あなたは 'データ型'を意味しますか? – Pynchia

+0

私は関数を呼び出し、何らかの形のデータ構造を返します。彼らは私にリストを与えることができます、彼らは私にセットを与えることができる、または彼ら自身の反復可能なクラスを実装することができます。私は、この構造体に順序があることを確認したいと思います。繰り返しを決めるときにも同じ方法で返します。 –

+0

例として、セットは順序付けられていません。リストが注文されます。テストケースが注文されていないので、セットは本質的にテストケースに失敗するはずです。リストが私のテストケースを通過するはずです。 –

答えて

3

私はそう思います、非常に面白いゲストです。 純粋なpython(ユーティリティコードなし) でコレクションが注文されているかどうかを確認する方法はありません。

あなたがcollections.Iterableタイプを使用することができますSequenceGeneratorType を確認するには)=のは、順次行く

をしてみましょう。

>>> 
>>> import collections 
>>> 
>>> result = [1,2,3,4,-1] 
>>> isinstance(result, collections.Iterable) 
True 
>>> 
>>> def generator_func(arg=10): 
...  for i in xrange(arg): 
...   yield i 
... 
>>> 
>>> generator_func() 
<generator object generator_func at 0x7f667c50f190> 
>>> 
>>> result = generator_func() 
>>> isinstance(result, collections.Iterable) 
True 

しかし:

>>> 
>>> result = {1,2,3,4,-1} 
>>> isinstance(result, collections.Iterable) 
True 
>>> 

それはあなたのために悪いケースです。 ので:あなただけcollections.Sequenceを使用する必要があり、この場合のために当然のことながら

>>> x = {1,2,3,-1} 
>>> x 
set([1, 2, 3, -1]) 
>>> [_ for _ in x] 
[1, 2, 3, -1] 
>>> x = {1,2,3,0} 
>>> x 
set([0, 1, 2, 3]) 
>>> [_ for _ in x] 
[0, 1, 2, 3] 
>>> import collections 
>>> isinstance(x, collections.Iterable) 
True 
>>> 

>>> result = {1,2,3,4,-1} 
>>> isinstance(result, collections.Sequence) 
False 
>>> isinstance({1:2, 3:3}, collections.Sequence) 
False 
>>> 

しかし:

>>> result = generator_func() 
>>> isinstance(result, collections.Sequence) 
False 
>>> 

したがって、私はSequence or GeneratorTypeをチェックする考えは素敵だと思います。だから、

>>> result = generator_func() 
>>> isinstance(result, (collections.Sequence, collections.Iterator)) 
True 
>>> result = [1,2,3,4,5] 
>>> isinstance(result, (collections.Sequence, collections.Iterator)) 
True 
>>> result = (1,2,3,4,5) 
>>> isinstance(result, (collections.Sequence, collections.Iterator)) 
True 
>>> result = {1,2,3,4,5} 
>>> isinstance(result, (collections.Sequence, collections.Iterator)) 
False 
>>> result = {1:1,2:2,3:3,4:4,5:5} 
>>> isinstance(result, (collections.Sequence, collections.Iterator)) 
False 
>>> 

Аbout順序は、このリンクをチェックしてください 。

商品の注文についてわからない場合は、 明示的に確認する必要があります。

«Explicitは暗黙的よりも優れています。»

>>> 
>>> def order_check(result, order_rule = cmp_rule): 
...  for item, next_item in zip(result, result[1:]): 
...   if not order_rule(item, next_item): 
...    return False 
...  return True 
... 
>>> def cmp_rule(item, next_item): 
...  if item < next_item: 
...   return True 
...  return False 
... 
>>> 
>>> result = [1,2,3,4,5] 
>>> order_check(result) 
True 
>>> result = [1,2,3,4,5,-1] 
>>> order_check(result) 
False 
>>> 

しかし、正直なところ、発電機は、あなたがそれで発生すると順序が同じになること を保証します。

-1

あなたは「注文」を持っているという性質の意味を完全には説明していません。あなたの "呼び出し可能な"良いアイデアです。私はあなたが "ダンダー"(ダブルアンダースコア)の方法を読んで、のうちの1つががあなたが望む定義と一致するかどうかを見ることをお勧めします。あなたが私たちに与えたことから、私は強く、__getitem__があなたが望むものだと思っています。構造上try-exceptブロックを設定する "ask forgiveness"メソッドもあります。

try: 
    dummy = (_ for _ in result) 
    has_order = True 
except: 
    has_order = False 
return has_order 
+1

最初の段落からは、OPすべてのサンプルコードチェックのための "iterable"を意味するだけではありません。 –

+0

私は同意します:この答えは非常に不十分です。 @カイル・ストランドはこれを貴重なものにしているので、私はここで答えを出して2点の控除をします。 :-) – Prune