iT邦幫忙

4

[不做怎麼知道系列之Android開發者的30天後端養成故事 Day2] - 建立自信心 #一起練Python語法 #不能拖 #先照著教學做

https://ithelp.ithome.com.tw/upload/images/20200204/20124548x78dO7x7f2.png

所以我說,剛開始要做什麼呢?

RS 個人覺得,不管學習什麼,不論是新技能、新知識,必須先在一開始就 迅速 建立 自信心,相信這一點大家都知道,但很多人會忽略一點是 迅速 兩個字,人閒著就很容易想東想西,一旦你沒有動手執行,隨著時間的經過,你的自信心會呈現非線性的衰弱狀態。

不知道你有沒有這樣子的經驗,有些事情做著做著,就突然感覺很有自信,覺得你問什麼問題我都可以回答你,沒在怕的;還有一個經驗是,以前明明很會做某件事,可是好一段時間沒再接觸了,突然有人問我以前很熟的事情,我卻懷疑自己認為的是不是真正的事實。

而快速建立自信的方法,就是 先照著教學做 就對了,而且執行的中間盡量不要休息或隔太久,讓自己保持在一個 啟動 的狀態,這就有點像是騎車的起步總是最難、靜止到移動需要克服最大靜摩擦力一樣,當你呈現啟動的狀態後,摩擦力相對就沒有像一開始那麼大。

這也是為什麼 30 天鐵人賽這麼迷人的地方,當你持續不間斷的做同一件事情,你會 非常 有信心,不信嗎? 你可以試試看。

https://images.pexels.com/photos/837306/pexels-photo-837306.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260

攝影師:bruce mars,連結:Pexels

沒有頁碼的目錄

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

  • 那我們就開始囉
    • 版本選擇 & 安裝
    • 第一支程式 (Hello World)
  • 基礎語法們
    1. 變數(Variables) & 資料型別 (Data Type)
      • 基本型別
      • 關於型別,你需要瞭解更多 (檢查記憶體、型別轉換、各種進位)
      • 區域變數 (Local variables) & 全域變數 (Global variables) & 作用範圍(Scope)
    2. 邏輯控制 (Control Statements)
      • if else & for loop
    3. 好用小技巧
      • 給多個變數單行指定同一個值
      • 給冗長或難讀的 function name 指定成一個好讀的別稱吧 !

那我們就開始囉

「工欲善其事,必先利其器」,而我們選定的框架是 Django,它是用 Python 寫的,我們在這 30 天也必須跟 Python 搞好關係,Python 是著名的好寫好上手,它不像 Java 一樣有很嚴格的型態宣告,大大地加快編寫程式碼的速度,當然有好就有壞的一面,這就是程式語言之間的戰爭了 XD

我們這邊將專注在熟悉 Python 的 語法,關於安裝、版本選擇、第一支程式可以參考以下文章:

版本選擇 & 安裝

  1. Python有許多版本,除非你有特殊需求,不然一律選擇 Python 3.x 的穩定版,有可以參考簡體文章 是选择学习 Python2 还是 Python 3?,內有分析各版的差異性。
  2. Windows 用戶可以參考 (2018 11 月的文章) 在Windows底下最適當安裝Python環境的方法,這位邦友已經先幫大家踩過雷了,請服用。
  3. Mac 用戶可以參考 (2015撰 2019更新) 在 Mac 上用 pyenv 輕鬆安裝 Python3 (可直接支援安裝多種版本),這位是用 terminal 中 brew 套件來安裝的,適合熟悉 terminal 的捧油們。
  4. 如果以上兩種都覺得太麻煩或看不懂,還可以參考 (2017 10月) 給自學者的Python教學(0) : 如何安裝Python(Mac/Windows),其中包含了 Windows 與 Mac 的安裝方法,而 Mac 是選用 pkg 安裝檔來安裝 Python,適合喜歡無腦安裝的捧油們。
  5. 至於 Linux 用戶,我相信你們都選擇用 Linux 了,應該有能力自己解決 XD

第一支程式 (Hello World)

Python 的開發方式有很多種,可以在 cmd 直接 > python、也可以在文字編輯器寫好再到 cmd 用 > python helloworld.py、也可以用 Jupyter Notebook、也可以用 IDE,總之就看每個人喜好的方式,RS 建議可以從 IDE 切入,在我們對一個程式語言不熟悉的時候,有時候 IDE 可以給我們一些錯誤提醒或智慧補齊程式碼等功能,可以參考 Python IDE and Python HelloWorld Program

基礎語法們

注意,雖然很基礎,但卻是寫出高品質程式碼,所不可忽略的部分,尤其是已經有點 coding 經驗的人們,學習另一個程式語言需要 避免傲氣,因為每個程式語言的特性都不一樣,可能兩種程式語言同樣都有 int 整數,可是其代表的值域可能不同,舉例來說,在極值的情況下,可能你的程式碼就出錯了,這時候可怪不了別人,總之,千萬不可因為你好像懂了,就自動跳過這個階段,怎麼判斷你懂了沒,一個簡單的判斷方式就是:「你能夠不看資料就回答出 python 有幾種資料型別,並且講出每個型別的值域範圍。」

還有另一個重點,就是 你必須自己執行你自己寫的程式碼,參考我的程式碼、修改參數、按下執行、檢查輸出值是不是和自己想像的相同,跟看 RS 寫的輸出結果,所帶來的感受度是完全不一樣的,透過修改參數,驗證自己的觀念是否正確,會帶給你無限大的自信。以上講的,都是 RS 本人痛過的經驗談。

  1. 變數 (Variables) & 資料型別 (Data Type)

    • 基本型別: Python 是隱式宣告(宣告變數時,不需要表明它的型別),所以你更需要清楚瞭解 !

        # ###################################################################
        # Boolean(布林/二元),值域範圍是 0(False) 和 1(True),注意: 是大寫
        # ###################################################################
        this_is_boolean = True
      
        # ###################################################################
        # String(字串)
        # ###################################################################
        this_is_string = "字串可以用 雙引號 所框起來"
        another_string = '也可以用 單引號 框起來,這兩種都是字串'
        more_specific_about_string = '''如果你的字太多,
        還可以用多行的方式呈現,
        只要三個單引號或三個雙引號就可以了。'''
        more_info = """
        用單、雙引號交錯的好處,
        就是你不需要使用跳脫字元(escape char,反斜線(\)),
        你可以在裡面大膽的用'單引號'
        有些情況還有跳脫你的跳脫,根本就像在玩風聲,我識破你的識破XD (誤
        e.g. 
        1. print("我想t吃飯")   # 輸出為: 我想t吃飯
        2. print("我想\t吃飯")   # 輸出為: 我想    吃飯
        3. print("我想\\t吃飯")  # 輸出為: 我想\t吃飯
        """
      
        # ###################################################################
        # Integer(整數),值域範圍在 Python 2 可以用 sys.maxint 來檢查最大值,
        # 而最小值自然就是 -sys.maxint-1,但這件事情在 Python 3 就不一樣了,
        # int 是沒有值域限制的,說是這樣說,但還是要看你的系統的位元數,
        # 可以用 sys.maxsize 來檢查,
        # 所以值域是在 -sys.maxsize-1 ~ sys.maxsize。
        # 
        # 但 RS 必須老實說,我自己也沒有搞得很懂 Python 3 的 int 範圍,
        # 我的電腦是 64-bit,"理論上最大值"應該要是 9223372036854775807,
        # 我卻可以將 int 設超過這個"最大值",如果大家有想法可以提出來救一下 RS。
        # 
        # 值得注意的是,在 Java 與 Kotlin 中,有區分出 Long(長整數),
        # Python 2 也還有 Long,而 Python 3 就只有 int。
        # ###################################################################
        this_is_int = 9487
      
        import sys    # 必須先引入 sys 套件,才可以使用
        max_int = sys.maxsize * 10
        print(max_int)          # 輸出為 92233720368547758070
        print(type(max_int))    # 輸出為 <class 'int'>
      
        # ###################################################################
        # Float(浮點數),值域範圍為 sys.float_info.min ~ sys.float_info.max
        # 值得注意的是,在 Java 與 Kotlin 中,
        # 有區分 float 與 double 這兩種精度不同的浮點數,
        # 而 Python 只有 float 這一種浮點數。
        # ###################################################################
        this_is_float = 3.14159
      
        min_float = sys.float_info.min
        max_float = sys.float_info.max
        print("float max: ", sys.float_info.max, 
            ", min: ", sys.float_info.min)
        # 輸出為 float max:  1.7976931348623157e+308, 
        # min:  2.2250738585072014e-308
      
        # ###################################################################
        # Complex(複數),也就是實數和虛數的結合,在極座標等運算較常用到,
        # 這裡先不討論。值得注意的是,這邊使用的是 j,而在數學上慣用的是 i。
        # ###################################################################
        this_is_complex = 1 + 2j
      

      基礎型別小結

      • Boolean 要記得大寫 (True, False)
      • Integer 理論值無上下限
      • Python 3 沒有 Long, Double 型別
    • 關於型別,你需要瞭解更多

        # ###################################################################
        # 怎麼確認一個變數的型別?
        # 假設我們用一個 Float 乘上一個 Int,那麼會變成什麼型別呢?
        # ###################################################################
        this_is_float = 0.9527
        this_is_int = 5278
        secret_variable = this_is_float * this_is_int
        print(type(secret_variable))    # 輸出為 <class 'float'>
      
        # ###################################################################
        # 各種進位該怎麼表示? 假設以十進位的 10,轉換成各種進位呢?
        # 十進位(Decimal)/ 二進位(Binary)/ 八進位(Octal)/ 十六進位(Hexadecimal)
        # ###################################################################
        decimal = 10
        binary = bin(decimal)
        octal = oct(decimal)
        hexa = hex(decimal)
      
        print("num: ", decimal, ", bin: ", binary, ", octal: ",
            octal, ", hex: ", hexa)
        # 輸出為 num:  10, bin:  0b1010 , octal:  0o12 , hex:  0xa
      
        # ###################################################################
        # 如何在各種基本型別中遊走? 如何轉換型別?
        # ###################################################################
      
        # 為了排版漂亮,各位就原諒 RS 不打 print 了齁
      
        # int/float/boolean to string
        int_to_string = str(100)         # 輸出為 100
        float_to_string = str(0.2266)    # 輸出為 0.2266
        boolean_to_string = str(True)    # 輸出為 True
        complex_to_string = str(2+3j)    # 輸出為 (2+3j)
      
        # string to int/float/boolean
        string_to_int = int("100")         # 輸出為 100
        string_to_int_base8 = int("14", 8) # 輸出為 12
        string_to_float = float("0.618")   # 輸出為 0.618
        string_to_boolean = bool("True")   # 輸出為 True
        string_to_boolean = bool("False")  # 輸出為 True
        # 有沒有覺得哪裡奇怪? 為什麼 bool("False") 會輸出 True?
        # 事實上,bool() 內只要有值,就會輸出 True
        # print(bool()) 或 print(bool("")) 就會輸出 False
        # 如果你沒有自己去替換這些參數
        # 或許發現這件事的時候,就是你的程式碼在系統出錯的時候了
        # 然後被老闆釘在牆上
        string_to_complex = complex("2-3j") # 輸出為 (2-3j)
        string_to_complex = complex(2, 3)   # 輸出為 (2+3j)
      
        # ###################################################################
        # 如何知道各個型別占多少記憶體?
        # 用 sys.getsizeof 來檢查看看你的記憶體配置吧
        # ###################################################################
      
        # 浮點數測試
        print(sys.getsizeof(3.14159))        # 輸出為 24
        print(sys.getsizeof(3.14e+100))      # 輸出為 24
        print(sys.getsizeof(3.14e-100))      # 輸出為 24
      
        # 整數測試
        print(sys.getsizeof(100))            # 輸出為 28
        print(sys.getsizeof(sys.maxsize))    # 輸出為 36
        print(sys.getsizeof(int(1e+308)))    # 輸出為 164
      
        # 自創型別測試
        class MyCustomObject:
            def __init__(self, var1, var2, var3):
                self.var1 = var1
                self.arbitrary = var2
                self.name = var3
      
        print(sys.getsizeof(MyCustomObject(1, 2, 3)))    # 輸出為 48
      
    • 區域變數 (Local variables) & 全域變數 (Global variables) & 作用範圍(Scope)

      Python 的 Scope 和 Java 有很大的不同,Java 除了 import 之外,所有變數、所有運算都要在 class 內宣告和執行,而 Python 雖然彈性,卻可能讓初學者替自己埋下許多坑。

        # 我們的全域變數,藉由觀察 global_var 在各階段的值,
        # 可以看出 Variables 與 Scope 的互動關係
        global_var = 10
      
        # 注意: 在 local scope 宣告的變數名稱,可以跟 global variable 同名,
        # 在邏輯上容易出錯,應盡量避免同名的用法
      
        def first_local_scope():
            local_var = 20     # 此為 local variable,
                               # 與 second_local_scope() 的 local_var,
                               # 雖然同名,但兩個是完全不相關的變數
      
            global_var = 30    # 此為 local variable,
                               # 與 global variable 的同名
            print("global_var: ", global_var, ", local_var: ", local_var)
      
      
        def second_local_scope():
            local_var = 40     # 此為 local variable,
                               # 與 first_local_scope 無相關
      
            # 在這個 local scope 中,雖然可以讀取到 global_var,
            # 但無法修改 global_var 的值,如真的需要修改,需加入 global 關鍵字
            print("global_var: ", global_var, ", local_var: ", local_var)
      
      
        def third_local_scope():
            global global_var
            global_var = 50    # 因為有先加入 global 關鍵字,
                               # 所以這次修改的是真正的全域變數
            print("global_var: ", global_var)
      
      
        # 真正的執行順序
        print("global_var: ", global_var)    # 輸出為 10,全域變數的初始值
        first_local_scope()                  # 輸出為 30, 20,
                                             # 此處輸出的是假的全域變數,
                                             # 事實上是區域變數
      
        second_local_scope()                 # 輸出為 10, 40,
                                             # 存取得到全域變數,
                                             # 可是無法修改
      
        third_local_scope()                  # 輸出為 50,
                                             # 此處修改的是真正的全域變數
      
        print("global_var: ", global_var)    # 輸出為 50,
                                             # 被 third_local_scope() 
                                             # 修改為 50
      

      關於更詳細的 Scope 測試,可以參考 (2017 5月) 有點複雜的 Python Scope,推薦從 Java 轉 Python 的人們研究。

      區域變數、全域變數、作用範圍小結

      • local scope 和 global scope 的變數可以取一樣的變數名稱,但不要找自己麻煩,盡量用變數名稱區分開來
      • 各個 local scopes 間的變數,不能互相修改
      • local scope 可以取用 global scope 的變數,但需要加入 global 的關鍵字
      • 盡量避免在 local scope 直接取用 global scope 變數,改用參數傳入與 return 的方式處理
  2. 邏輯控制 (Control Statements)

    • if else & for loop

      讓我們一起來用任性的鬼抓人小遊戲感受一下迴圈以及邏輯判斷:

        print("鬼抓人開始!")
      
        # 值得注意的點是,counter 的值是從 0 到 11,不會到 12
        for counter in range(0,12):
        	if counter == 10:
        		print("數到十囉,我要去抓人囉。")
        	elif counter > 10:
        		print("原來時間已經到了喔,我竟然還在發呆沒去抓人。")
        	else:    # 除了等於、大於,剩下的自然就是小於的情況囉
        		print("現在數到 ", counter)
      
        print("遊戲結束")
      

      輸出結果

        鬼抓人開始!
        現在數到  0
        現在數到  1
        現在數到  2
        現在數到  3
        現在數到  4
        現在數到  5
        現在數到  6
        現在數到  7
        現在數到  8
        現在數到  9
        數到十囉,我要去抓人囉。
        原來時間已經到了喔,我竟然還在發呆沒去抓人。
        算了,我不玩了。
      

      值得注意的地方是,沒有 ++-- 來做變數遞增遞減,到現在還是很不習慣QQ,至於 Python 為什麼沒有,可以參考 Python integer incrementing with ++

  3. 好用小技巧

    • 給多個變數單行指定同一個值

        a = b = c = 10
        print("a = ", a, ", b = ", b, ", c = ", c)    # 輸出為 10, 10, 10
      
    • 給冗長或難讀的 function name 指定成一個好讀的別稱吧 !

        def just_print(var1):
            print(var1)
      
      
        custom_name = just_print    # 將原本可能很長或可讀性不好的 function,
                                    # 指定成一個自己好讀的別稱
        custom_name(10)             # 輸出為 10
      

單日心得總結

先跟各位說抱歉,今天的量已經讓文章長到不好閱讀了,畢竟要在一篇的篇幅,把這麼多東西塞進去真的很不容易,很想把基本但卻占篇幅的講完,但這是文章,不是出書QQ。

從各標題的篇幅就可以抓到 RS 覺得的重點在哪裡,光是變數就占了一半,因為基礎,才要更瞭解,希望大家可以耐住性子,真的花點時間,自己做過一次這些觀念驗證,找到自己的知識盲區那瞬間會很興奮哈哈。

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

喜歡我的文章嗎? 趕快來看看我都發了什麼文章吧:我的文章目錄

歡迎閱讀我的上一篇: [不做怎麼知道系列之Android開發者的30天後端養成故事 Day1] - 起源 #我是誰 #為什麼 #目標

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


2 則留言

0
Yanwei Liu
iT邦新手 5 級 ‧ 2020-02-05 08:39:52

期待您的文章~

感謝你的支持,真是太感動了嗚嗚QQ
隔壁同事問我為何看著留言涕泣不知所云

0
sheep630459
iT邦新手 5 級 ‧ 2020-02-12 22:29:15

邦友您好,因為覺得文章中提到int大小還蠻有趣的就去查了一下
主要是是對python來說如果整數大小超過系統位元限制時,會將其以軟體的方式去實作
而sys.maxsize這個function則是回傳Py_ssize_t 型別能夠容納的最大正整數,這個數字則是各種object的大小限制(list, string, dict)
參考資料:
https://stackoverflow.com/questions/48138632/in-python-what-is-sys-maxsize
https://stackoverflow.com/questions/20987390/cython-why-when-is-it-preferable-to-use-py-ssize-t-for-indexing/20987501

原來如此! 終於能理解了,感謝 sheep630459 ~

提供一點整理在這裡給其他人參考:

引用自 In Python, what is sys.maxsize? 的留言

The maximum number of elements a list can contain. It is not the largest value an int can have, but the largest index the basic structures can contain, since outside this scope, it is no longer addressable.

sys.maxsize 的 9223372036854775807 並不是 的最大值,而是 記憶體指標的最大值,代表你的任何物件放在超過 sys.maxsize 之外的記憶體,那系統是無法去讀取到的,這個跟作業系統有關係。

我要留言

立即登入留言