2011-10-12 75 views
6

我的一個測試單元檢查一個範圍是否在讀取日誌文件後正確設置,我想測試var == range(0,10)。但是,range(0,1) == range(0,1)在Python 3中的計算結果爲False如何測試等效範圍

是否有直接的方法來測試Python 3中的範圍等價性?

+2

你爲什麼要比較兩個範圍? –

+0

我的單元測試只是斷言範圍是正確構造的。在該程序中,不是存儲最小和最大可接受值,而是存儲範圍,然後測試val是否在範圍內。 – oneporter

回答

10

在Python3,range返回range類型的迭代。兩個range s爲等於當且僅當它們是相同的(即分享相同的id。)爲了測試其內容平等,轉換rangelist

list(range(0,1)) == list(range(0,1)) 

此工作正常的短範圍。對於很長的範圍,Charles G Waldman's solution更好。

+0

@oneporter:被警告,這消耗了迭代器,你將無法在稍後重新調用它。 –

+2

@StevenRumbalski:由於'range'對象是可迭代的,而不是迭代器,所以它們不能被「消耗」。 [你可以迭代它們多次。](http://ideone.com/RGvxv) –

+2

@Sven Marnach。優秀。感謝您的更正。 –

1

嘗試assertItemsEqual,(在docs):

class MyTestCase(unittest.TestCase): 
    def test_mytest(self): 
     a = (0,1,2,3,4) 
     self.assertItemsEqual(a, range(0,4)) 
+0

請注意,assertItemsEqual在py3中不可用,這是OP所要求的。 – jmagnusson

6

第一個建議的解決方案 - 使用「list」將範圍轉換爲列表 - 是無效的,因爲它會首先將範圍對象轉換爲列表(如果範圍很大,可能消耗大量內存),然後比較每個元素。考慮例如a =範圍(1000000), 「範圍」對象本身很小,但如果將它強制爲一個列表,它將變得非常龐大。那麼你必須比較一百萬個元素。

答案(2)效率更低,因爲assertItemsEqual不僅要實例化列表,還要在進行元素比較之前對它們進行排序。

相反,由於您知道對象是範圍,因此當它們的步幅,起始值和結束值相等時,它們是相等的。例如。

ranges_equal = len(a)==len(b) and (len(a)==0 or a[0]==b[0] and a[-1]==b[-1])

+3

如果範圍步驟不起作用。例如範圍(1,20,2)和範圍(1,20)將是等效的。 – krs1

+0

好點krs1。我認爲我的方法可以通過比較範圍的len()來解決....或者,如果避免空範圍的問題:'ranges_equal =(len(a)== len(b)和a [0] == b [0]和a [-1] == b [-1]) –

+0

= len(b)和a [0] == b [0]和a [-1] == b [-1] –

1

另一種方式來做到這一點:

ranges_equal = str(a)==str(b)

字符串表示指示開始,結束和範圍的步驟。

這個問題讓我覺得,也許Python應該提供一種方法來從範圍對象本身獲取這些屬性!