[不做怎麼知道系列之Android開發者的30天後端養成故事 Day3] - 讓熱情燒一會兒 #別間斷很重要 #Python資料結構

基礎語法後,沒意外就是進階了吧 !?

嘖嘖嘖,別急,還記得 Day1 參考了 backend roadmap 後所提出的七步驟嗎?,今天我們要正式踏入第一步驟 - 資料結構,我已經聽到你們的「蛤~~~到第三天了還在第一步驟 !?」,俗話說得好:「走得慢一點,踩得穩一點,重要的是走得遠。」,人生不是短跑衝刺競賽,或許你們和 RS 一樣是社會新鮮人,或許有些社會歷練,又或許你們已是社會老鳥,但至少你我都至少還期望自己會再戰個幾年吧 ?,就是這個 幾年,有個幾年的時間就夠了,我們只是前面走得慢一點,瞭解得深一點,後來會省很多 Debug 的時間,到時候才知道誰走的快。

沒有頁碼的目錄

避免加上程式碼會讓文章冗長,所以先上目錄,各位看官可以挑選自己有興趣或不足的章節:

Python 的 資料結構

  • list

    在 Python 的 listJavaKotlinArrayList 概念幾乎一樣,你可以把它們想成同一個結構,都是 有序可變,可是要注意的是 list 裡面裝的資料,是不是可以容許 多種型別 在同一個 list ****?,在 Java 的世界,ArrayList 不能 裝不同型別,這句話會有爭議,因為聰明如你們的工程師們想出了各種解法,有興趣可以參考 Create an ArrayList with multiple object types?;在 Kotlin 的世界,和 Java 一樣也是 不能 裝不同型別,依舊有各種解法,可以參考 Declaring List of multiple types in Kotlin;而 Python 的 list 是 可以 裝下多種型別 的,所以在使用上必須特別注意,這也是 RS 為什麼在 Day2,花這麼多時間強調變數型別的原因。

    以 RS 的使用經驗來說,RS 建議讓 list 只裝同樣型別的資料,在進行專案實作上,比較不會讓自己和其他人搞混,減少出錯的機會。而總是會有需要裝下不同型別資料的時候,就可以使用接下來介紹的 tuple,晚點再說,先來看看怎麼用 list 吧。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    # 先放入各種型別的變數
    minteger = 10
    mstring = "Hi, this is RS."
    mfloat = 3.14159
    incremental_list = range(10)
    float_list = [8.787, -0.618, 3.14e+30]

    # 用 中括號[] 包起來,
    # 就是 python 宣告 list 的方法

    # 再全部塞到一個混和型別的 list,
    # 除了用變數放入,也可以直接塞入值
    # list 內也可以塞入另一個 list
    mix_type_list = [minteger, mstring,
    mfloat, incremental_list, float_list,
    "I bought a keychron k6, nice~"]

    # ###############################
    # 取用 list 內的資料的方式
    # ###############################

    # 可直接看到 list 全部的資料
    print(mix_type_list)
    # 輸出為: [10, 'Hi, this is RS.',
    # 3.14159, range(0, 10),
    # [8.787, -0.618, 3.14e+30],
    # 'I bought a keychron k6, nice~']

    # 可從前面數來的 index 取用
    print(mix_type_list[1])
    # 輸出為 Hi, this is RS.

    # index 也可從後面數來
    print(mix_type_list[-1])
    # 輸出為 I bought a keychron k6, nice~

    # 取用 list 內的 list 的資料,
    # 可用 len(your_list) 來取得你的 list 長度
    # list 不像陣列(Array)需要事先宣告大小
    print(mix_type_list[len(mix_type_list)-2][0])
    # 輸出為 8.787
    • as Stack

      在 Python 想要使用 Stack 不需要自己實作,直接使用 list 的 appendpop 操作即可。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      # 因 list 內建 append(), pop()
      # 可以直接模擬出 stack 的效果

      # Python 的 list 的最後一個逗號,
      # 可以寫出來,也可以省略
      list_as_stack = [0, 1, 2, 3, ]
      print(list_as_stack)
      # 輸出為 [0, 1, 2, 3]

      # 在 list 的最後放入一個值
      list_as_stack.append(4)
      print(list_as_stack)
      # 輸出為 [0, 1, 2, 3, 4]

      # 從最後一項拿出
      be_popped = list_as_stack.pop()
      print(list_as_stack)
      # 輸出為 [0, 1, 2, 3]
      print(be_popped)
      # 輸出為 4

      # 值得注意的是,pop 可以傳入 index 參數,
      # 這個 index 是從前面數過來的正順序,
      # 而 pop() 的預設參數為 -1,
      # 也就是指向最後一個,使用時需要自行注意!

      # 如果要避免犯錯,可以自己用 list.pop()
      # 實作出一個沒有參數的 pop() function,
      # 強制只能 pop 最後一項
    • as Queue

      在 Python 想使用 Queue 的話,你可以利用上面提到的 appendpop 來當作 queue,但是,官方文件有提到,這樣的使用效率不好,原因是因為 list 的查找實作方式適合取用最後一項,有興趣可以參考 Efficiency of using a Python list as a queue,想更瞭解的話,可以修演算法 (Algorithms) 的課程,通常都會教怎麼去判斷程式的執行效率。

      官方建議,可以使用 deque 來解決效率問題,改用 popleft,來取值。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      # 依舊可以使用 list 的 append 和 pop
      # 來達到 queue 的效果,但效率不佳
      # 量大 且 時常需要新增、取出的時候
      # 效率問題將會更明顯
      list_as_queue = [0, 1, 2, 3]
      print(list_as_queue)
      # 輸出為 [0, 1, 2, 3]

      # 與 stack 相同,是放到最後
      list_as_queue.append(4)
      print(list_as_queue)
      # 輸出為 [0, 1, 2, 3, 4]

      # 以 pop(0) 取出在 list 的第一項,
      # 在實作面是從最後一項走訪到第一項
      # 所以當你的 list size 越大,就越沒效率
      out_of_queue = list_as_queue.pop(0)
      print(list_as_queue)
      # 輸出為 [1, 2, 3, 4]
      print(out_of_queue)
      # 輸出為 0

      # 使用 collections.deque
      # 將 list 轉為 deque,
      # 再用 popleft(),取得第一項
      from collections import deque
      effective_queue = deque(list_as_queue)
      print(effective_queue)
      # 輸出為 deque([1, 2, 3, 4])

      out_of_queue = effective_queue.popleft()
      print(effective_queue)
      # 輸出為 deque([2, 3, 4])
      print(out_of_queue)
      # 輸出為 1
  • tuple

    這個就是在樓上 list 有提到的 tuple,RS 建議適合用在 混和型別 的情況,通常是你有一堆資料要傳出去,要創一個 class 又太麻煩的時候,特別適合使用 tuple,tuple 還有一個特性是 不可變 (immutable),也就是說當你創立一個 tuple 後,如果要新增/刪減,那麼就需要重新再創一個,你不能修改它。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # tuple 可加小括號,也可不加,
    # 但有加小括號的話,是比較好閱讀的
    this_is_a_tuple = 10, 8.787, "哩賀"
    tuple_with_parentheses =
    ("我是 RS", 1.7878, 99)
    print(this_is_a_tuple)
    print(tuple_with_parentheses)

    # 還有一種情況是 RS 常用的,
    # 就是在輸出一些很雜的資料的時候
    import datetime
    print("嗨 RS,", "現在時間是",
    datetime.datetime.now(),
    ",\n本周天氣是", ["晴天", "陰天",
    "晴天", "晴天", "晴天",
    "晴天", "晴天"])
    # 輸出為 嗨 RS,
    # 現在時間是 2020-02-05 19:28:15.395380
    # 本周天氣是 ['晴天', '陰天', '晴天',
    # '晴天', '晴天', '晴天', '晴天']
  • dict (Dictionary)

    如果有用過 Java 或 Kotlin 的捧油們,可以把 dict 想成 HashMap,都是 <key, value> 配對的形式,使用方法非常彈性,key 和 value 可以放入各種型別,目前 RS 試過的 key 有不能放 list 、set 和 dict,都是 unhashable,大家可以玩玩看,非常有趣,可是實際的使用情境上,還是盡量不要這麼花式,不然連自己都不知道自己在寫什麼。關於 hashable 可以參考 What is the meaning of ‘unhashable type’ error in Python?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    # dictionary 可以塞入的型別非常彈性
    dictionary = {2048: "好玩", 3.14159:
    ("這是", "pi", "拉"), "我是key": [1, 2, 3, 4, 5]}
    print(dictionary)
    # 輸出為 {2048: '好玩', 3.14159:
    # ('這是', 'pi', '拉'),
    # '我是key': [1, 2, 3, 4, 5]}

    # 也可以額外新增一筆資料進去
    dictionary[8.787] = {"裡面": "還可以包含另一個dict哦"}
    print(dictionary)
    # 輸出為 {2048: '好玩', 3.14159:
    # ('這是', 'pi', '拉'), '我是key':
    # [1, 2, 3, 4, 5], 8.787:
    # {'裡面': '還可以包含另一個dict哦'}}

    # 嘗試更多 key 能接受的型別
    dictionary[("連key", "都可以是tuple")] = "太扯拉"
    print(dictionary)
    # 輸出為 {2048: '好玩', 3.14159:
    # ('這是', 'pi', '拉'), '我是key':
    # [1, 2, 3, 4, 5], 8.787:
    # {'裡面': '還可以包含另一個dict哦'},
    # ('連key', '都可以是tuple'): '太扯拉'}
  • set

    和 dictionary 一樣,在 Java、Kotlin 中也有對應的結構 - HashMap,而 set 的特性是 無排序項目不重複,適合用在你有一些資料是不希望有重複值的時候,set 與 set 之間還有取交集(intersect)、聯集(union)、差集(difference)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # set 和 dictionary 都是用大括號包起來,
    # 不要眼花看錯囉,這時候命名就很重要了。
    this_is_set = {9527, "你跟我重複就只會剩一個哦",
    "你跟我重複就只會剩一個哦", 9487, 2266, 9527}

    print(this_is_set)
    '''
    輸出為
    {'你跟我重複就只會剩一個哦', 2266, 9487, 9527}
    '''

最後,推薦大家閱讀 (2018 12月) 輕鬆學習 Python:資料結構,裡面提到很多以上資料結構的操作細節。

攝影師:Vladislav Vasnetsov,連結:Pexels

單日心得總結

其實 RS 在寫文章的時候,都很糾結到底要舉多少範例,每個結構的各種用法就已經足夠寫成一篇文章,希望各位看官們不要太鞭我的範例包含太少QQ。

今天超開心能參加 好想工作室 的羽球團,趁這個機會認識到好多大神們,不然平常都是待在自己位置上敲鍵盤沒機會聊天,開勳 <3。

這連續兩天都在學習觀念和語法,真的有點太無趣,明天就一起進入到 Django 的世界吧 !

我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。


  • 喜歡我的文章嗎? 趕快來看看我都發了什麼文章吧:我的文章目錄
  • 歡迎閱讀我的上一篇: [不做怎麼知道系列之Android開發者的30天後端養成故事 Day2] - 建立自信心 #一起練Python語法 #不能拖 #先照著教學做
  • 歡迎閱讀我的下一篇: [不做怎麼知道系列之Android開發者的30天後端養成故事 Day4] - 動手做做看 #捲起袖子 #初探Django # DjangoHelloWorld
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2021-2022 Sam Ho
  • Visitors: | Views:

請我喝杯咖啡吧~

支付宝
微信