天天看點

python3學習筆記之清單和元組清單元組基礎清單和元組的存儲差異清單元組性能差異清單元組使用場景總結思考題

文章目錄

  • 清單元組基礎
  • 清單和元組的存儲差異
  • 清單元組性能差異
  • 清單元組使用場景
  • 總結
  • 思考題

清單元組基礎

清單和元組,都是一個可以放置任意資料類型的有序集合

  • 清單是動态的,長度大小不固定,可以随意地增加、删減或者改變元素(mutable)。而元組是靜态的,長度大小固定,無法增加删減或者改變(immutable)。
  • Python 中的清單和元組都支援負數索引,-1 表示最後一個元素,-2 表示倒數第二個元素
  • 清單和元組都支援切片操作
    li = [2,4,6,8]
    li[1:3]
    [4,6]
    
    tup = (1,3,5,7)
    tup[0:2]
    (1,3)
               
  • 清單和元組都可以随意嵌套
  • 清單元組可以通過list()和tuple()函數互相轉換
    tuple([2,4,6,8])
    (2,4,6,8)
    list((1,3,5,7))
    [1,3,5,7]
               
  • 清單和元組常用内置函數
    • count(item)表示統計清單 / 元組中 item 出現的次數
      li = [2,4,6,8,2]
      li.count(2)
      2
                 
    • index(item)表示傳回清單 / 元組中 item 第一次出現的索引
      li = [2,4,6,8,2]
      li.index(2)
      0
                 
    • list.reverse()和list.sort()分别表示原地倒轉清單和排序(ps:元組沒有這兩個内置函數)
      li = [2,4,6,8,2]
      li.reverse()
      [2,8,6,4,2]
                 
    • reversed() 和 sorted() 同樣表示對清單 / 元組進行倒轉和排序,reversed() 傳回一個倒轉後的疊代器,sorted() 傳回排好序的新清單。此處對元組和清單的操作不是原地操作
      tup = (1,3,5,7)
      reversedTup = reversed(tup)
      for item in reversedTup:
          print(item,end = ' ' )
      7 5 3 1
      
      sortedTup = sorted(tup,reverse = True)#預設reverse為False,為False時按從小到大順序排序
      print(sortedTup)
      (7,3,5,1)
                 

清單和元組的存儲差異

l = [1, 2, 3]
l.__sizeof__()
64
tup = (1, 2, 3)
tup.__sizeof__()
48
           

你可以看到,對清單和元組,我們放置了相同的元素,但是元組的存儲空間,卻比清單要少 16 位元組。why???

由于清單是動态的,是以它需要存儲指針,來指向對應的元素(上述例子中,對于 int 型,8 位元組)。另外,由于清單可變,是以需要額外存儲已經配置設定的長度大小(8 位元組),這樣才可以實時追蹤清單空間的使用情況,當空間不足時,及時配置設定額外空間

l = []
l.__sizeof__() // 空清單的存儲空間為40位元組
40
l.append(1)
l.__sizeof__() 
72 // 加入了元素1之後,清單為其配置設定了可以存儲4個元素的空間 (72 - 40)/8 = 4
l.append(2) 
l.__sizeof__()
72 // 由于之前配置設定了空間,是以加入元素2,清單空間不變
l.append(3)
l.__sizeof__() 
72 // 同上
l.append(4)
l.__sizeof__() 
72 // 同上
l.append(5)
l.__sizeof__() 
104 // 加入元素5之後,清單的空間不足,是以又額外配置設定了可以存儲4個元素的空間
           

上面的例子,大概描述了清單空間配置設定的過程。我們可以看到,為了減小每次增加 / 删減操作時空間配置設定的開銷,Python 每次配置設定空間時都會額外多配置設定一些,這樣的機制(over-allocating)保證了其操作的高效性:增加 / 删除的時間複雜度均為 O(1)。

**ps:**資料量較小時,清單和元組的在存儲上的性能差異可以忽略不計,但對于海量資料(一億甚至十億資料)這種存儲上的資料不能忽略

清單元組性能差異

元組要比清單更加輕量級一些,是以總體上來說,元組的性能速度要略優于清單

  1. 資源緩存:python會在背景會對一些靜态資料做一些資源緩存(resource caching),對于元組這些靜态變量若它不被使用且占用空間不大時,python的垃圾回收并不會立即回收這部分記憶體,下次若建立同樣大小的元組時,可以直接利用之前緩存的記憶體資源,這樣可以大大加快程式運作速度。而對于清單這種非靜态資料若這些變量不被使用會被python的垃圾回收機制立馬回收。
  2. 元組初始化速度快于清單,如下可以看出元組出事化速度要比清單塊5倍
    python3 -m timeit 'x=(1,2,3,4,5,6)'
    20000000 loops, best of 5: 9.97 nsec per loop
    python3 -m timeit 'x=[1,2,3,4,5,6]'
    5000000 loops, best of 5: 50.1 nsec per loop
               
  3. 索引操作元組和清單速度差别可忽略不計
  4. 對元素的增加删除或改變,清單顯然由于清單(元組必須通過建立一個元組來完成)

清單元組使用場景

  1. 如果存儲的資料和數量不變,比如你有一個函數,需要傳回的是一個地點的經緯度,然後直接傳給前端渲染,那麼肯定選用元組更合适。
  2. 如果存儲的資料或數量是可變的,比如社交平台上的一個日志功能,是統計一個使用者在一周之内看了哪些使用者的文章,那麼則用清單更合适。

總結

清單和元組都是有序的,可以存儲任意資料類型的集合,差別主要在于下面這兩點。

  1. 清單是動态的,長度可變,可以随意的增加、删減或改變元素。清單的存儲空間略大于元組,性能略遜于元組。
  2. 元組是靜态的,長度大小固定,不可以對元素進行增加、删減或者改變操作。
  3. 元組相對于清單更加輕量級,性能稍優。

思考題

# 建立空清單
# option A
empty_list = list()

# option B
empty_list = []
           

A、B 兩種方式,請問它們在效率上有什麼差別嗎?我們應該優先考慮使用哪種呢?

answer:A、B 兩種方式差別主要在于list()是一個function call,Python的function call會建立stack,并且進行一系列參數檢查的操作,比較expensive,反觀[]是一個内置的C函數,可以直接被調用,是以效率高。