2015-10-28 4 views
10

Ich schreibe eine Reihe von Testfällen für Python-Neulinge. Eines der Probleme, die ich bei meinen Tests festgestellt habe, ist, dass es möglich ist, falsch positive Ergebnisse zu erhalten. Sie haben vielleicht Glück gehabt und zufällig jedes Element in der richtigen Reihenfolge gegeben, aber sie sollten wirklich eine Struktur verwenden, die geordnet ist.Wie kann ich feststellen, ob eine Struktur in Python Ordnung hat?

Bis jetzt ist dies die beste Lösung, die ich mir vorstellen konnte.

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

aber ich fühle mich nicht sicher GeneratorType wirklich bestellt ist, oder dass dieser Test ist umfassend. Ich denke, es sollte einen besseren Weg geben, um dies zu testen. Wie prüfe ich, dass eine Struktur Ordnung hat?

+1

Es ist ziemlich schwer zu verstehen, was Sie nach. Bitte geben Sie Beispiele an. Nach Struktur meinen Sie "Datentyp"? – Pynchia

+0

Ich rufe eine Funktion und es gibt irgendeine Form der Datenstruktur zurück. Sie könnten mir eine Liste geben, sie könnten mir ein Set geben, oder sie könnten ihre eigene iterierbare Klasse implementieren. Ich möchte sicherstellen, dass diese Struktur Ordnung hat, und wird auf die gleiche Weise zurückkehren, unabhängig davon, wann ich mich dazu entschließe zu iterieren. –

+0

Als Beispiel wird ein Set nicht bestellt. Eine Liste ist bestellt. Ein Satz sollte von Natur aus meine Testfälle nicht bestehen, da er nicht bestellt wurde. Eine Liste sollte meine Testfälle bestehen. –

Antwort

3

Ich denke, es ist sehr interessant guestion. Es gibt keine Möglichkeit in reinem Python (ohne Dienstprogramm-Code) zu überprüfen, ob die Sammlung bestellt ist.

der Reihe nach Let go =)

Sequence oder GeneratorType Um zu überprüfen Sie collections.Iterable Typ verwenden können.

>>> 
>>> 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 

Aber:

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

Es ist schlimm Fall für Sie. Denn:

>>> 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 
>>> 

Natürlich für diesen Fall sollten Sie eine collections.Sequence nur verwenden.

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

Aber:

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

So denke ich, dass eine Idee zu überprüfen Sequence or GeneratorType schön. Überprüfen Sie diesen Link:

So:

>>> 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 bestellen.

Wenn Sie nicht sicher sind über die Reihenfolge der Artikel, Ich denke, Sie sollten sie explizit überprüfen.

«Explizit ist besser als implizit.»

>>> 
>>> 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 
>>> 

Aber, ehrlich gesagt, Generatoren garantieren , dass die Reihenfolge die gleiche sein würde, wie Sie darin erzeugen.

-1

Sie haben nicht vollständig beschrieben, was Sie mit der Eigenschaft "Order" meinen; Ihr "Callable" ist eine gute Idee. Ich schlage vor, dass Sie durch die "Dunder" (Doppel-Unterstrich) Methoden lesen, ob eine von ihnen die gewünschte Definition entspricht. Von dem, was Sie uns gegeben haben, vermute ich stark, dass __getitem__ ist, was Sie wollen. Es gibt auch das „Vergebung bitten“ Verfahren zur Herstellung eines try-except-Block auf der Struktur Einstellung:

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

Vom ersten Absatz, ist es klar, dass OP bedeutet nicht nur "iterierbar", was für alle Beispielcode-Prüfungen gilt. –

+0

Ich stimme zu: Diese Antwort ist ziemlich unzureichend. @Kyle Strand macht dies zu einem wertvollen Punkt, also werde ich die Antwort hier lassen und den 2-Punkte Abzug nehmen. :-) – Prune

Verwandte Themen