2014-09-22 118 views
10

我想了解列表數據結構的in命令和index()的內部工作。列表和索引函數列表[Python]

當我說:

if something not in some_list : 
    print "do something" 

是它內部遍歷整個列表,類似於for環或不會使用,像hashtables

而且在列表中的index()更好的方法,使如果該項目不在列表中,則顯示錯誤。 inindex()的工作是否一樣?如果index()更好,那麼是否有可能在產品不存在的情況下發現錯誤,並且如果可能的話,編程是否很好?

+0

的O趣味插圖(N):'$對於i 1 2 3 4 5; do python -mtimeit -s「l = range(int(1e $ i))」「(-1)not in l」; done' – 2014-09-23 00:15:30

回答

12

好問題!是的,你提到的兩種方法都必須迭代列表。 Python不會爲列表使用哈希表,因爲沒有限制列表元素是可哈希的。

如果你知道關於"Big O" notation,則list數據結構被設計用於O(1)訪問,通過查找一個已知索引(例如, my_list[13]。成員測試是O(n)。

還有其他數據結構針對O(1)速度進行成員資格測試(即__contains__),即setdict。這些實施與hashtables

下面是如何使用IPython驗證組和列表time-complexity,來確認這些權利要求的示例:

In [1]: short_list, long_list = range(1000), range(10000) 

In [2]: timeit 'potato' not in short_list 
10000 loops, best of 3: 40.9 µs per loop 

In [3]: timeit 'potato' not in long_list 
1000 loops, best of 3: 440 µs per loop 

In [4]: small_set, big_set = set(short_list), set(long_list) 

In [5]: timeit 'potato' not in small_set 
10000000 loops, best of 3: 72.9 ns per loop 

In [6]: timeit 'potato' not in big_set 
10000000 loops, best of 3: 84.5 ns per loop 
1

對於列表,不幸的是,兩種方法(inindex())迭代列表以檢查您正在查找的項目。只要知道了成員資格測試的結果,他們就會停止迭代,這意味着如果未找到該項目,它們將迭代到最後。我知道,如果你必須使用列表,not in構造是最Python和你應該去的(但你應該轉儲這些不必要的括號)。

如果您不需要專門使用列表,內置的set類型可以經常使用。該集合是一個類似於列表的數據結構,但它使用哈希算法來測試項目的存在,所以如果您正在做很多類型的工作,則可以考慮切換。閱讀我已鏈接的文檔,因爲集合是無序的,所以它們不支持切片或索引等。

是的,你可以計劃你正在檢查的項目在你的數據結構中不存在的時間。您正在尋找一個Try/Except Block

example_list = [1,2,3] 

try: 
    index_of_4 = example_list.index(4) 
except ValueError: 
    print("Oops! 4 wasn't in the list!") 

當你知道你的程序中可能會出現異常,你可以用有問題的代碼塊這樣優雅地捕捉並從異常恢復。儘可能優雅地從錯誤和異常中恢復,這確實是很好的編程實踐,即使這意味着只是打印出錯信息並退出。