---
# System prepended metadata

title: Python3' Note

---

Python-基礎
---

* shell腳本範例：

  ```
  $ vi shell.sh
  ```
  
  ``` sh
  1 ls
  2 pwd
  3 ls /
  ```
  
  ```
  $ chmod u+x shell.sh
  $ ll
  -rwxrw-r-- 1 apple apple 12 1月 01 00:00 shell.sh // shell.sh 變成可執行檔
    
  $ ./shell.sh // 執行shell.sh
  shell.sh
  /home/apple/Desktop
  bin    etc   .  .  .  .
  boot   home
  etc    .
  cdrom  .
  data   .
  dev    .
  // 原本在ls pwd底下的功能也能在shell.sh使用!!!
  ```
  
* C 語言範例

  `$ vi apple.c`
  ``` C
  #include<studio.h>
  int main(int argc,char ** argv)
  {
      printf("Hello,world"\n);
      return 0;
  }
  ```
    * 編譯
      ```
      $ ls
      apple.c 
      $ gcc apple.c //編譯apple.c
      $ ls
      apple.c a.out
      $ ./a.out
      Hello,world
      ```
    * 如果我想改成 "Hello你媽"?
      
      `$ vi apple.c`
      ``` C
      #include<studio.h>
      int main(int argc,char ** argv)
      {
          printf("Hello你媽"\n);
          return 0;
      }
      ```
      
      ```
      $ ./a.out
      Hello,world // 竟然沒變？為何!!!因為沒有編譯
      $ gcc apple.c
      $ ./a.out
      Hello你媽
      
    * 綜上，C的運行過程：編輯>編譯>運行 (編輯完後編譯)

* Python 範例
 
  `$ vi banana.py`
  
  ``` py
  print("Hello,world")
  ```
  
  ```
  $ python banana.py // 執行py : python 檔名
  Hello, world
  ```
  
  `$ vi banana.py`
  
  ``` py
  print("Hello你媽")
  ```
  
  ```
  $ python banana.py
  Hello你媽
  ```
  * 綜上，Python事實上是 編輯+編譯 > 運行 (編輯時同步編譯)

* 運行 python
  `$ python 1.py(檔名)` : 運行 1.py
  
* python shell : 執行程式碼片段的 REPL 環境

  ``` Terminal
  $ python or python3 # 使用 python2(3) 運行
  >>> exit() # 離開
  ```
  
  ``` Terminal
  $ ipython or ipthon3 # 使用 ipython(3) 運行，並支持Terminal 指令
  
  In [1]: ls
  apple.py
  
  In [2]: exit # 離開
  ```
  
* 註釋

  * 單行註釋 #
  
    ``` python
    # Hello 你媽
    print("Hello你媽") # Hello 你媽
    ```
    
  * 多行註釋 ''' 或 """
   
    ``` python
    ''' 我是多行註釋，我超酷
    今天天氣好
    我愛Python
    '''
    ```
    
    ``` python
    """ 我真的超酷
    今天天氣差
    我不愛c
    """
    ```
    
  * 如果 py 檔裡面有中文(包括註釋) `$ python`會無法運行
    ``` Terminal
    $ vi apple.py
    ```
    ``` vim
    1 # 輸出一些字
    2 print("python 不讓我運行")
    ```
    ``` Terminal
    $ python apple.py
      File "hello_world.py", line 1
    SyntaxError: Non-ASCII character '\xe8' in file hello_world.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
    
    $ python3 apple.py
    python 不讓我運行
    ```
  * 此時於開頭加入`#coding=utf-8` 或 `# -*- coding:utf-8 -*-` 
   
    ``` Terminal
    $ vi apple.py
    ```
    
    ``` python
    1 # -*- coding:utf-8 -*-
    2
    3 '''# coding=utf-8'''
    4
    5 # 輸出一些字
    6 print("python 不讓我運行")
    ```
    
    ``` Terminal
    $ python apple.py
    python 不讓我運行
    ```

變量 : 儲存數據
---

```python
apple_price = 35 # 定義了一個變量(apple_price),他的值是35(元)
apple_weight = 2.5 # 購買蘋果2.5(斤)

money = apple_price * apple_weight # 這也是一個變量,他的值就是price * weight
money = money - 10 # 首次出現才是變量，此時money已非首次出現，故非變量，而是給予已經存在的變量(money)賦上一個新的值
```

* input

  ```python
  name = input("請輸入名字:") # 使用者輸入之內容將會賦予在name中
  ```
  * python2 & python3 於 input("") 大不相同
  
    * python2
     
      ```Terminal
      $ python
      >>> a = input("name:")
      name:Ryan
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "<string>", line 1, in <module>
      NameError: name 'Ryan' is not defined
      ```
    * python3
    
      ```Terminal
      $ python3
      >>> a = input("name:")
      name:Ryan
      >>> a
      name:Ryan
      ```
    * 原因：python2 將 `input()` 輸入的東西視為code而執行 
      ```Terminal
      $ python
      >>> a = input("age:")
      age:1+4
      >>> a
      5 # python3 的輸出結果會是 1+4
      ```
    * 解決辦法：`a = raw_input()` ->  python3沒有此Function，不過此Function的功能跟py3裡的 `input()`是一樣的
      ```Terminal
      $ python
      >>> a = raw_input()
      1+4
      >>> a
      '1+4'
      ```
* `print()`

  * 如果我想要輸出我的年齡
    
    `$ vi print_age.py`
    ```python
    age = 18
    print("age")
    ```
    ```Terminal
    $ python3 print_age.py
    age 
    # 為何是age而非18呢!!!
    # 因為print("")會打印出""裡面的字
    ```
    `$ vi print_age.py`
    ```python
    age = 18
    print("age是:%d"%age) # %age會取age的值輸入到%d中
    ```
    ```Terminal
    $ python3 print.py
    age是:18
    ```
    
  * 如果我想輸入名字？
  
    `$ vi print_name.py`
    ```python
    name = "大中天"
    print("名字是:%d"%name)
    ```
    ```Terminal
    $python3 print_name.py
    Traceback (most recent call last):
      File "print_name.py", line 2, in <module>
        print("name:%d"%name)
    TypeError: %d format: a number is required, not str
    # %d不能放string
    ```
    ```python
    # "" -> 係屬於String 不能使用%d，而需使用%s
    # 故現在只需將 %d 改成 %s 即可 
    name = "大中天"
    print("名字是:%s"%name)
    ```
    ```Terminal
    $ python3 print_name.py
    name:大中天
    ```
  * Homework：打印一個名片

    `$ vi print_business_card.py`
  
    ```python
    # 輸入
    name = input("name:")
    phone_number = input("Phone number:")
    address = input("address:") 

    # 輸出
    print("==============")
    print( "Name: %s" %name )
    print( "Phone number: %s" %phone_number )
    print( "Address: %s" %address )
    print( "==============")
    ```
  
    ``` Terminal
    $ python3 print_business_card.py
    name:apple
    Phone number:098764321
    address:太麻里隔壁
    ==============
    Name: apple
    Phone number: 098764321
    Address: 太麻里隔壁
    ==============
    ```
    
  * 一次輸出多個
    
    `vi print.py`
    
    ```python
    name = "ryan"
    age = 25
    addr = "太麻里隔壁"

    print("name:%s,age:%d,addr:%s"%(name, age, addr)) # 用,隔開, 並用()刮起來
    ```
    
    ```Terminal
    python3 print.py
    name:ryan,age:25,addr:太麻里隔壁
    ```
* ID 規則
  
  * 由字母, _, 數字組成，數字不得當開頭
    
    `a_1 = 1` 可以
    `_a1 = 1` 可以
    `1_a = 1` 不行，數字在開頭
    `1!a = 1` 不行，有"!"
    `1-a = 1` 不行，有"-"
    
  * 可讀性
  
    `a = 100` 這啥？
    `appleprice = 100` 不好閱讀
    `apple_prict = 100` 推薦
    `applePrice = 100` 可以
    `ApplePrice = 100` 可以
  
  * keyword 不能使用
   
    ```Terminal
    $ ipython3
    In [1]: import keyword # 導入 keyword
    In [2]: keyword.kwlist  # keyword 的 list
    Out[2]: ['False', 'None', 'True',...]
    # 列出來的都不能用！
    ```
  
if 判斷語句
---

* 格式
  ``` python
  if 條件:
      條件成立時, Do something
  ```
  `$ vi if.py`
  
  ```python=
  age = 15
  
  if age > 18:
      print("Happy")
  ```
  
  ```Terminal
  $ python3 vi if.py
  # 條件沒有成立，print("Happy") 沒有被執行
  ```
  
  `vi if.py`
  
  ``` python=
  age = 20
  
  if age > 18:
      print("Happy")
  ```    
  
  ```Terminal
  $ python3 vi if.py
  Happy # 條件成立，print("Happy") 被執行
  ```
  
* 運算符

    * 比較運算符
    
      ```python
      if a >= 3: # 如果 a≥3 
          print("")
      ```    
      
      |運算符|描述|
      |:--:|:--:|
      |>|>|
      |<|<|
      |==|=|
      |>=|≥|
      |<=|≤|
      |!=|≠(較為通用)|
      |<>|≠(py3不支援)|
      
    * 邏輯運算符 and/ or/ not
    
      ``` python=
      deposit = int(input("deposit:"))
      hobbies = input("你愛喝茶嗎？(Y/N)")
      sweet_and_ice_level = input("甜度冰塊？")

      if deposit >= 25 and hobbies == "Y" and sweet_and_ice_level == "微微":
          print("烏龍綠好喝")
      else:
          print("窮鬼沒品味")
      ```
      
      |運算符|舉例|
      |:-:|:-:|
      |and|`if a >= 0 and a < 50`<br/>`print("50>a≥0")`|
      |or|`if drink == "四季" or drink == "八冰綠"`<br/>`print("50嵐好喝")`|
      |not|`if not (a >=0 and a < 50)`<br/>`print("a ≤ 0 or a > 50")`|
    
* 使用 input 的 if 問題
  
  `$ vi if2.py`
  
  ```python=
  age = input(age:)
  
  if age > 18:
      print("Happy")
  ```    
  
  ```Terminal
  $ python3 if2.py
  age:19
  Traceback (most recent call last):
    File "if.py", line 3, in <module>
      if age > 18:
  TypeError: '>' not supported between instances of 'str' and 'int'
  ```
  
  `vi if2.py`
  
  ```python=
  age = input(age:) # input獲取的數據皆視為str age: > 19 > "19"
  
  age_num = int(age) # 將age轉為 int
  
  if age_num > 18: # 轉為int之後，兩者才有比較之可能
      print("Happy")
  ```
  
  ```Terminal
  $ python3 if2.py
  age:20
  Happy
  ```

  * 變量類型

    * Number
   
      * int
      * long
      * float
      * complex
  
    * String
    * List
    * Tuble
    * Dictionary
    * Boolean

  * 查詢類型 `$ type`
  
    ```Terminal
    $ python3
    >>>a = 1
    >>>b = 1.1
    >>>c = "1"
    >>>
    >>> type(a)
    <class 'int'>
    >>> type(b)
    <class 'float'>
    >>> type(c)
    <class 'str'>
    
* if_else

  `vi if2.py`
  
  ```python
  age = input(age:) # input獲取的數據皆視為str age: > 19 > "19"
  
  age_num = int(age) # 將age轉為 int
  
  if age_num > 18: # 轉為int之後，兩者才有比較之可能
      print("Happy")
      
  else:
      print("Unhappy") # 條件不滿足時，輸出 print("Unhappy")
  ```
  
  ```Terminal
  $ python if2.py
  age:15
  Unhappy
  ```
  
* if_elif

  ```python=
  num = int(input("請輸入數字(1-7)"))
  
  if num == 1:
      print("星期一")
  elif num == 2:
      print("星期二")
  elif num == 3:
      print("星期三")
  elif num == 4:
      print("星期四")
  elif num == 5:
      print("星期五")
  elif num == 6:
      print("星期六")
  elif num == 7:
      print("星期日")
  else:
      print("你智障嗎？")
      
  ```
  
while 循環
---

* 如果我想從1輸出到10
  
  * 使用前面幾個學到的概念
  
      ```python=
      print(1)
      print(2)

      # 或

      num = 1
      print(num)

      num = num + 1
      print(num)
      # 一直重複？太麻煩了
      ```
      
  * 使用 while
  
    ```python=
    num = 1
    
    while num <= 10: # 當 num≤10 時(條件滿足)，會循環執行，直到條件不滿足(num>10)止
        print(num)
        num = num + 1 # 這必須寫! 否則條件會永遠滿足，不停執行
        
    ```
    
嵌套(Nesting)
---

* if
 
    ```python=
    ticket = 1 # 1:有買票 0:沒買票
    knife_lenght = 3 #cm

    if ticket == 1:
        print("歡迎光臨，麻煩配合安檢")
        if knife_lenght <= 5: # 當if ticket成立時，才會執行此判斷
            print("歡迎光臨")
    else:
        print("沒票來這衝三小")
    ```
    ```python=
    thirsty = input("Are you thirsty?(Y/N)")

    if thirsty == "Y":
        deposit = int(input("deposit:"))
        hobbies = input("你愛喝茶嗎？(Y/N)")
        sweet_and_ice_level = input("甜度冰塊？")

        if deposit >= 25 and hobbies == "Y" and sweet_and_ice_level == "微微":
            print("烏龍綠好喝")
        else:
            print("窮鬼沒品味")
    else:
        print("騙誰啊?")  
    ```    
    
* while

  * Q. 減肥操
    1. 站
    2. 坐
    3. 站
    4. 轉五圈
    5. 坐
    ```python=
    sport = 1

    while sport <= 10:
        print("Stand")
        print("Sit")
        print("Stand")

        cycle = 1
        while cycle <= 5:
            print("cycle")
            cycle = cycle + 1

        print("Sit")
        sport = sport + 1
    ```
  * Q. 輸出
    1. \*
    2. \**
    3. \***
    4. \****
    5. \*****
    ```python=
    # 我自己寫的
    n = 1
    while n<= 5: 
        print("*"*n)
        n = n + 1
    ```
    ```python=
    # 老師的寫法，看起來比較屌XD
    i = 1
    while i <= 5:
        
        j = 1
        while j <= i:
            print("*", end="")
            j+=1
            
        print("")
        
        i+=1
    ```    
  * Q.
    1. \*****
    2. \*****
    3. \*****
    4. \*****
    5. \*****
    
      ```python=
      # 我自己寫的
      
      n = 1
      while n <= 5: 
          print("*"*5)
          n = n + 1
      ```
      
    * `print("5", end="")`
    
      ``` python=
      i = 1
      
      while i <= 5:
      
          j = 1
          while j <=5:
              # print 默認換行，要讓他不換行 
              print("*", end="")  
              j = j + 1 
              # 在c 語言中, 想讓 j加1的方式:
              # j++; ++j; j+=1; j=j+1;
              # 在python中，只有後兩種
              # 以後都寫第三種!!!
          print("")
          
          i = i + 1 # i+=1
      ```
      
      * 複合賦值運算符
        
        |運算符|舉例|
        |-|-|
        |+=|a+=c 等於 a=a + c|
        |-=|a-=c 等於 a=a - c|
        |*=|a*=c 等於 a=a * c|
        |/=|a/=c 等於 a=a / c|
        |%=|a%=c 等於 a=a % c|
        |**=|a**=c 等於 a=a ** c|
        |//=|a//=c 等於 a=a // =c|
        
        ==注意==
        
        ```Terminal
        $ python3
        >>> a = 3
        >>> a *= 3+9-10+23 
        >>> a
        75
        
        #他是 a = a * (3+9-10+23) = 3 * 25
        #而非 a = a*3+9-10+23 = 31 !!!
        ```
        
    * ==99_multiplication==
      
      ![](https://i.imgur.com/VwG1Sob.png)
      
      ```python=
      a = 1
      while a <= 9:
          
          b = 1
          while b <= a:
              print("%d*%d=%d \t"%(b,a,a*b),end="") # \t 相當於一個 tab ，可以達成對齊的效果
              b += 1
              
          print("")
          
          a += 1
      ```
      
* ==Rock_paper_scissor==
  
  ```python=
  # 導入random module
  # Head_first p.30
  import random 
  
  player = int(input("Enter:Rock(0) Paper(1) scissor(2)"))
  computer = random.randiat(0,2)
  
  # 執行很多組判斷時，用()隔開！！！
  if (player==0 and computer==2) or (player==1 and computer==0) or (player==2 and computer==1):
      print("Win")
      
  elif player == computer:
      print("Draw")
      
  else:
      print("Lose")
  ```
  
* Print("All even numbers between 1 and 100")
  ```python=
  a = 1
  
  while a<=100:
  
      if a%2==0: # 如果a/2沒有餘數時
          print(a)
          
      a+=1
  ```
* ## break
  `$ vi break.py`
  ```python=
  a = 1
  while a<=5:
      print(a)
      a+=1
      
      if a == 3:
          break  # break 能立即結束while循環之執行
  ```
  ```Terminal
  $ python3 break.py
  1
  2
  ```
  
  `vi Twenty_1-100_even_numbers`
  ```python=
  a = 1
  num = 0
  
  while a<=100:
  
      if a%2==0:
          print(a)
          num+=1
          
      if num == 20:
          break
          
      a+=1
  ```

* ## continue
  `vi continue.py`
  ```python=
  a = 1
  while a<=5:
      a+=1
      
      print("----")
      if a==3: # 如果a=3時
          continue # 結束此次循環，直接執行下一次循環
      print(a)
  print("====")
  ```
  ```Terminal
  $ python continue.py
  ----
  2
  ----
  ----
  4
  ----
  5
  ----
  6
  ====
  ```
  


for
---
```Terminal
$ ipython3
In [9]: a = "temporary"                                                         

In [10]: a                                                                      
Out[10]: 'apple'

In [11]: for temp in a: 
    ...:     print(temp) 
    ...:                                         
a
p
p
l
e
# for 會對數據內容做循環
```
Int vs String
---
* [CPU](https://zh.wikipedia.org/wiki/%E4%B8%AD%E5%A4%AE%E5%A4%84%E7%90%86%E5%99%A8)
  * 處理速度快
  * 存取空間少
* [HDD](https://zh.wikipedia.org/wiki/%E7%A1%AC%E7%9B%98)
  * 處理速度慢
  * 存儲空間多
* 由於CPU大部分時間都在等待HDD的回應，為了提速而發展出[RAM](https://zh.wikipedia.org/wiki/%E9%9A%8F%E6%9C%BA%E5%AD%98%E5%8F%96%E5%AD%98%E5%82%A8%E5%99%A8)
  * 速度與空間介於兩者間

* 1 G = 2^30^ = 1024 M
  1 M = 2^20^ = 1024 K
  1 K = 2^10^ = 1024 Byte
  1 [Byte(B)](https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82) = 8 [bit(b)](https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%85%83)
  
* bit是一種0與1的狀態，而Byte即可有 00000000, 00000001, 00000010, ..., 11111111 等 ==256== 種狀態( 2^8^ ), 故 1 Byte 可以表示的值為 0~255

```Terminal
In [1]: num = 100
In [2]: num2 = "100"
In [3]: # 最大的不同在於 100 可以存於 1 Byte (<255)
In [4]: # 而 "100" 係 "1" "0" "0" 分別存於 Byte，
In [5]: # 如果 Interpreter (解釋器) 係以 C 語言寫的，會再多一個 "\0"
In [6]: # 故 "100" 共花了 4 Byte 來存取
 
In [7]: int(num2) # 可以將num2的輸出轉成int
Out[7]: 100
In [8]: str(num) # 也可以將num轉成str
Out[8]: "100"
In [9]: len(num2) # 可以查看num2有多長
Out[9]: 3 # 事實上還有一個"\0", 但 python 不會算進去
```

* 加法
 ```Terminal
 $ ipython3
 
 In [1]: a = "壹佰"
 In [2]: b = "塊"
 In [3]: A = 10
 In [4]: B = 90
 
 In [5]: c = a + b
 In [6]: c
 Out[6]: '壹佰塊'
 In [7]: C = A + B
 In [8]: C
 Out[8]: 100
 
 In [9]: d = "===" + a + b + "==="
 In [10]: d
 Out[10]: '===壹佰塊==='
 In [11]: e = "===%s==="%(a+b)
 In [12]: e           
 Out[12]: '===壹佰塊==='
 ```
* Index
  ```Terminal
  In [1]: name = "abcdefgh" 
  In [2]: name[3] # index 正數，從左至右
  Out[2]: 'd'
  In [3]: name[0] # index 從 0 開始!
  Out[3]: 'a'
  In [4]: name[8] # 超過範圍時會錯誤
  IndexError: string index out of range
 
  In [5]: len(name)
  Out[5]: 8
  
  In [6]: name[len(name)-1]
  Out[6]: 'h'
  In [7]: name[-1] # 負數即從右至左算起, 從 -1 開始
  Out[7]: 'h'
  In [8]: name[-2]
  Out[8]: 'g'
  ```
  
* 切片
  ```Terminal
  # [Start:End:步長]
  
  In [1]: name = "abcdefgABCDEFG" 
  In [2]: name[2:5] # 始於 name[2]，終於 name[5] 的前一位(name[4])
  Out[2]: 'cde' # e 是 name[4]
  In [3]: name[2:-1] # 始於 name[2], 終於 name[-2]
  Out[3]: 'cdefgABCDEF'
  
  # 我想取至最後一位呢？name[2:0]?
  In [4]: name[2:0]
  Out[4]: '' # 空的!! 因為 index[0] 是 "a"
  In [5]: name[2:] # 要取至最後一位就空著就行了
  Out[5]: 'cdefgABCDEFG'
  
  # 我想跳著取呢？
  In [6]: name[2::2] # 步長就是一次走幾格
  Out[6]: 'cegBDF'
  In [7]: name[2::1]
  Out[7]: 'cdefgABCDEFG' # 沒制定步長, 預設就是1
  
  # 我想到著取呢? (逆序)
  In [8]: name[::-1]
  Out[8]: GFEDCBAgfedcba
  ```
  
List []
---

* 當我想存取多個數據時，且該數據類型相同， 定義多個變量並不實際， 此時List即派上用場

```Terminal
$ ipython3

In [1]: name = ["a", "b", "c"] # 定義了一個 List
In [2]: name
Out[2]: ['a', 'b', 'c']

# C 語言的數據: int num[]={1, 2, 3, 4, 5}
# 只能單一Type 定義
In [3]: name2 = [1, 0.1, "1"]  # python 可同時定義不同Type的數據

# 增刪改查

# 增.append()
In [4]: name.append("d")
In [5]: name
Out[5]: ['a', 'b', 'c', 'd'] # append 會增加在 list 的 index[-1]

# 增.insert(位置, 內容)
In [6]: name.insert(0, "A") # 插入 "A" 於 index[0]
In [7]: name 
Out[7]: ['A', 'a', 'b', 'c', 'd'] 

# 增.extend()
In [8]: name.extend(name2) # list + list
In [9]: name
Out[9]: ['A', 'a', 'b', 'c', 'd', 1, 0.1, "1"]

In [#]: # vs. append
In [#]: z = [1,2,3]
In [#]: x = [4,5]
In [#]: z.append(x)
In [#]: z
Out[#]:[1,2,3,[4,5]] # append會將整個列表當成一個整體加進來

# 刪.pop()
In [10]: name.pop() 刪除 index[-1]
Out[10]: ["1"]

# 刪.remove(內容)
In [11]: name.remove("A") # remove可指定內容刪除
In [12]: name
Out[12]: ['a', 'b', 'c', 'd', 1, 0.1]

In [13]: name.append("a")
In [14]: name
Out[14]: ['a', 'b', 'c', 'd', 1, 0.1, 'a']
In [15]: name.remove("a")
In [16]: name
Out[16]: ['b', 'c', 'd', 1, 0.1, 'a'] # .remove() 會從 index[0] 開始搜尋該內容，找到並刪除後即停止(只刪一次)

# 刪 del XXX[位置]
In [17]: del name[2]
In [18]: name
Out[18]: ['b', 'c', 1, 0.1, 'a']

# 改 xxx[位置] = 內容
In [19]: name[2] = "apple"
In [20]: name
Out[20]: ['b', 'c', 'apple', 0.1, 'a']

# 查 in / not in
In [21]: if "apple" in name:
    ...:      print("找到了")
    ...:
找到了

In [22]: if "apple" not in name:
    ...:     print("找不到")
    ...:

# 切片 [::]
In [23]: name[2:5]
Out[23]: ['apple', 0.1, 'a'] # 從list切片出來的內容還是list

In [24]: a = "abcdef"
In [25]: a[2:5]
Out[25]: 'cde' # 從字符串切片出來的東西還是字符串

```

* ==Name Managentment System== (modify)未完成

  * 先完成框架

    `$ vi name_managentment_system.py`
    ```python=
    # print
    print("="*10)
    print("Names Managentment System")
    print(" 1: append name ")
    print(" 2: delete name ")
    print(" 3: modify name ")
    print(" 4: inquire name ")
    print("="*10)

    # input
    num = int(input("Please input the function number: "))

    # function

    #append
    if num==1:
        pass # 不知道要寫啥時，先寫pass讓程式跳過這個指令
    #delete
    elif num==2:
        pass
    #modify
    elif num==3:
        pass
    #inquier
    elif num==4:
        pass
    else:
        print("輸入有誤")
    ```
    ```Terminal
    $ python3 names_management_system.py 
    ==========
    Names Managentment System
     1: append name 
     2: delete name 
     3: modify name 
     4: inquire name 
    ==========
    Please input the function number: 1
    
    $ python3 names_management_system.py 
    ==========
    Names Managentment System
     1: append name 
     2: delete name 
     3: modify name 
     4: inquire name 
    ==========
    Please input the function number: 7
    輸入有誤
    ```
  * 完成 append function
  
    `$ vi name_managentment_system.py`
    ```python=10
    # input
    num = int(input(" Please input the function number: "))
    names = [] # 建立一個空的list
    # function

    #append
    if num==1:
        append_name = input("Append name: ")
        names.append(append_name)
        print(names) 
    ```
    ```Terminal
    $ python3 name_managentment_system.py
    
    ==========
     Please input the function number: 1
    Append name: a
    ['a']
    
    $
    # 每輸入一次就退出程序，因為if判斷完即完成指令
    ```
    `$ vi name_managentment_system.py`
    ```python=10
    # 讓程序不停重複迴圈
    while True: # 下面註解

        # input
        num = int(input(" Please input the function number: "))
        names = [] # 建立一個空的list
        # function

        #append
        if num==1:
            append_name = input("Append name: ")
            names.append(append_name)
            print(names)
        #delete
        elif num==2:
            pass
        #modify
        elif num==3:
            pass
        #inquier
        elif num==4:
            pass
        else:
            print("輸入有誤")
     ```
     ```Terminal
     # while True 註解
     
    $ ipython3
    
    In [1]: a = 10
    In [2]: if a>5:
       ...:     pass
       ...:
    In [3]: a>5
    Out[3]: True # 條件成立
    In [4]: a<5
    Out[4]: False # 條件不成立
    ```
    ```Terminal
    $ python3 name_managentment_system.py
    ==========
     Please input the function number: 1
    Append name: a
    ['a']
     Please input the function number: 1 # 沒有直接結束程序了，因為會持續迴圈
    Append name: b
    ['b'] # 竟然不是 ['a', 'b'] ?
    
    # 因為 names = [] 也在迴圈內，每迴圈一次 name就重置回空list
    ```
    `$ vi name_managentment_system.py`
    ```python=10
    names = [] # 建立一個空的list

    # 讓程序不停重複迴圈
    while True:

        # input
        num = int(input(" Please input the function number: "))
    ```
    ```Terminal
    $ python3 name_managentment_system.py
    ==========
     Please input the function number: 1
    Append name: a
    ['a']
     Please input the function number: 1
    Append name: b
    ['a', 'b']
    ```
  * 完成其他 Function
  
    `$ vi name_managentment_system.py`
    ```python=17
    
    # function

    #append
    if num==1:
        append_name = input("Append name: ")
        names.append(append_name)
        print(names)
        
    #delete
    elif num==2:
        remove_name = input("Delete name: ")
        names.remove(remove_name)
        print(names)
        
    #modify 還沒想到怎麼解，因為modify需要知道index
    elif num==3:
        pass 
        
    #inquier
    elif num==4:
        inquier_name = input("Inquier name: ")
        if inquier_name in names:
            print("有")
        else:
            print("沒有")
        
    else:
        print("輸入有誤")
    ```
    ```Terminal
    $ python name_managentment_system.py
    
    ==========
     Please input the function number: 1
    Append name: a
    ['a']
     Please input the function number: 1
    Append name: b
    ['a', 'b']
     Please input the function number: 1
    Append name: c
    ['a', 'b', 'c']
     Please input the function number: 2
    Delete name: b
    ['a', 'c']
     Please input the function number: 4
    Inquier name: a
    有
     Please input the function number: 4
    Inquier name: d
    沒有
    ```
    
  * 新增離開功能
  
    `$ vi names_management_system.py`
    ```python=
    # print
    print("="*10)
    print("Names Managentment System")
    print(" 1: append name ")
    print(" 2: delete name ")
    print(" 3: modify name ")
    print(" 4: inquire name ")
    print(" 5: end")
    print("="*10)

    names = [] # 建立一個空的list

    # 讓程序不停重複迴圈
    while True:

        # input
        num = int(input("Please input the function number: "))

        # function

        #append
        if num==1:
            append_name = input("Append name: ")
            names.append(append_name)
            print(names)

        #delete
        elif num==2:
            remove_name = input("Delete name: ")
            names.remove(remove_name)
            print(names)

        #modify 還沒想到怎麼解，因為modify需要知道index
        elif num==3:
            pass

        #inquier
        elif num==4:
            inquier_name = input("Inquier name: ")
            if inquier_name in names:
                print("有")
            else:
                print("沒有")

        #end
        elif num==5:
            break
        else:
            print("輸入有誤")
    ```
    ```Terminal
    $ python3 names_management_system.py 

    Please input the function number: 5
    $
    ```
    
Dictionary {}
---
當我想存取多種不同類型的數據，也許Dictionary是個好選擇
* ## vs List
  ```Terminal
  $ ipython3
  
  In [1]: a = [1, "a", "b"]
  In [2]: print("%s, %d, %s"%(a[1], a[0], a[-1]))
  a , 1, b
  
  # list 要查詢時需要知道 Index，要列出來一一數在第幾個位置，如果list資料有一萬筆呢？
  
  #dict = {Key: Value}
  In [3]: b = {"a":"apple", "b":"book", "c":"car"}
  In [4]: print("%s, %s, %s"%(b["a"], b["b"], b["c"])
  apple, book, car
  
  #dirt 可以輸入指定的key來輸出資訊
  ```
  
* 增刪改查

  ```Terminal
  $ ipython3
  
  In [1]: a = {"a":1, "b":2, "c":"C", "d":"D"}
  
  # 增，改 xxx[key] = value
  In [2]: a["e"] = "E" # []沒有在dict裡時，則會新增
  In [3]: a 
  Out[3]: {'a': 1, 'b': 2, 'c': 'C', 'd': 'D', 'e'= 'E'}
  
  In [4]: a['c'] = 3 # []有在dict裡時，則會修改
  In [5]: a                       
  Out[5]: {'a': 1, 'b': 2, 'c': 3, 'd': 'D', 'e'= 'E'}
  
  # 刪 del xxx[key]
  In [6]: del a["e"]
  In [7]: a
  Out[7]: {'a': 1, 'b': 2, 'c': 3, 'd': 'D'}
  
  # 查 xxx.get(key)
  In [8]: a.get("a")
  Out[8]: 1 # 如果有的話就會顯示他的 value
  In [9]: a.get("e") # 沒有"e"的key，所以也就沒有對應的value
  ```
 
* 常見功能
  
  ```Terminal
  $ ipython3
  
  In [#]: a = {"a":1, "b":"B"}
  
  In [#]: a.get("a")
  Out[#]: 1
  
  In [#]: if "a" in a:
     ...:     print("有")
     ...:
  有
  
  In [#]: len(a)
  Out[#]: 2
  
  In [#]: a.keys()
  Out[#]: dict_keys(['a', 'b'])
  In [#]: for temp in a.keys():
     ...:     print(temp)
     ...:
  a
  b
  
  In [#]: a.values()
  Out[#]: dict_values([1, 'B'])
  In [#]: for temp in a.values():
     ...:     print(temp)
     ...:
  1
  B
  
  In [#]: a.items()
  Out[#]: dict_items([('a', 1), ('b', 'B')]) # 注意！他將 key 跟 value 裝進 tuple 裡
  In [#]: for temp in a.items():
     ...:     print(temp)
     ...:
  ('a', 1)
  ('b', 'B')
  
  # 畢竟 tuple 只能查閱，如果我想增改刪，可以取他的值出來輸出
  In [#]: for temp in a.items():
     ...:     print("key=%s, vaule=%s"%(temp[0], temp[1]))
     ...:
  key=a, value=1
  key=b, value=B
  
  # 另種寫法
  In [#]: for a,b in a.items():
     ...:     print("key=%s, value=%s"%(a,b))
     ...:
  key=a, value=1
  key=b, value=B # 下開註解
  ```
  ```Terminal
  $ ipython3
  
  In [#]: a = (1,2)
  In [#]: x,z = a
  In [#]: x
  Out[#]: 1
  In [#]: z
  Out[#]: 2
  ```
  
* ==Business_Card==

  `$ vi business_card_managentment_system.py`
  ```python=
  # print
  print("="*10)
  print(" 1.append")
  print(" 2.delete")
  print(" 3.modify")
  print(" 4.inquire")
  print(" 5.end")
  print("="*10)
    
  # 需要一個列表來存取所有名片
  business_card = []
  while True:
  
      # input
      num = int(input("請輸入功能數字: "))
        
      # function
      
      if num == 1:
          pass
      elif num == 2:
          pass
      elif num == 3:
          pass
      elif num == 4:
          pass
      elif num == 5:
          break
      else:
          print("輸入有誤")
    ```
    `$ vi business_card_managentment_system.py`
    
    ```python=19
        if num == 1:
            new_name = input("name:")
            new_phone = input("phone:")
            new_addr = input("address:")

            new_info = {}
            new_info["name"] = new_name
            new_info["phone"] = new_phone
            new_info["addr"] = new_addr

            business_card.append(new_info)
            print(business_card)
    ```
    ```Terminal
    $ python3 business_card_managentment_system.py
    
    請輸入功能數字: 1
    name:a
    phone:a
    address:a
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}]
    請輸入功能數字: 1
    name:b
    phone:b
    address:b
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}, {'name': 'b', 'phone': 'b', 'addr': 'b'}]
    ```
  * 新增一個功能：顯示所有名片
  
    `$ vi business_card_managentment_system.py`
    ```python=
    # print
    print("="*10)
    print(" 1.append")
    print(" 2.delete")
    print(" 3.modify")
    print(" 4.inquire")
    print(" 5.顯示所有名片")
    print(" 6.end")
    print("="*10)
    ```
    ```python=37
        elif num == 5:
            for temp in business_card:
                print(temp)
        elif num == 6:
            break
    ```
    ```Terminal
    $ python business_card_managentment_system.py
    請輸入功能數字: 1
    name:a
    phone:1
    address:1
    [{'name': 'a', 'phone': '1', 'addr': '1'}]
    請輸入功能數字: 1
    name:b
    phone:1
    address:1
    [{'name': 'a', 'phone': '1', 'addr': '1'}, {'name': 'b', 'phone': '1', 'addr': '1'}]
    請輸入功能數字: 5
    {'name': 'a', 'phone': '1', 'addr': '1'}
    {'name': 'b', 'phone': '1', 'addr': '1'}
    ```
  * 讓名片顯示更人性化些，且讓輸入功能前空一行
  
    `$ vi business_card_managentment_system.py`
    ```python=37
        elif num == 5:
            print("name\tphone\taddr") #\t 對齊
            for temp in business_card: #下面註解
                print("%s\t%s\t%s"%(temp["name"], temp["phone"], temp["addr"]))
        elif num == 6:
            break
        else:
            print("輸入有誤")

        print("") # 空一行
    ```
    ```Terminal
    # for in 註解
    $ ipython3
    
    In [1]: a = [{"a":"A", "b":1}, {"a":"C", "b":2}]                                
    In [2]: for temp in a: 
       ...:     print(temp) 
       ...:                                                                         
    {'a': 'A', 'b': 1}
    {'a': 'C', 'b': 2} # for會循環一次[]裡的元素

    In [3]: for temp in a: 
       ...:     print(temp["a"]) # 只輸出"a"的value
       ...:      
       ...:                                                                         
    A
    C
    ```
    
    ```Terminal
    $ python3 business_card_managentment_system.py
    
    請輸入功能數字: 1
    name:a
    phone:a
    address:a
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}]

    請輸入功能數字: 1
    name:b
    phone:b
    address:b
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}, {'name': 'b', 'phone': 'b', 'addr': 'b'}]

    請輸入功能數字: 5
    name	phone	addr
    a	a	a
    b	b	b
    ```
    
    `vi business_card_managentment_system.py`
    
    ```python=38
        elif num == 4:
            find_name = input("name: ")
            for temp in business_card:
                if find_name == temp["name"]:
                    print("%s\t%s\t%s"%(temp["name"], temp["phone"], temp["addr"]))
                else:
                    print("查無此人")
    ```
    ```Terminal
    $ python business_card_managentment_system.py
    
    請輸入功能數字: 1
    name:a
    phone:a
    address:a
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}]

    請輸入功能數字: 1
    name:b
    phone:b
    address:b
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}, {'name': 'b', 'phone': 'b', 'addr': 'b'}]

    請輸入功能數字: 5
    name	phone	addr
    a	a	a
    b	b	b

    請輸入功能數字: 4
    name: a
    a	a	a
    查無此人 

    請輸入功能數字: 4
    name: b
    查無此人
    b	b	b

    請輸入功能數字: 4
    name: c
    查無此人
    查無此人
    
    # 那麼多查無此人是三小
    # 因為for找a時，第一圈有找到a 所以輸出a的資料，然後又繼續第二圈(b)，所以多了一個查無此人！bc亦同
    # 解決辦法：找到後，break結束循環？
    # 但這樣只能解決a(a第一圈就找到而跳出)，bc一樣會有查無此人
    # 大絕招！直接給予 True / False
    ```
    
    `vi business_card_managentment_system.py`
    
    ```python=38
        elif num == 4:
            find_name = input("name: ")
            
            flag = False # 在for之前先設一個標記為錯誤
            for temp in business_card:
                if find_name in temp["name"]:
                    print("%s\t%s\t%s"%(temp["name"], temp["phone"], temp["addr"]))
                    flag = True # 當有找到時，標記為正確
                    #break (沒有意義，True就出去了)
            if flag == False:
                print("查無此人")
    ```
    ```Terminal
    $ python3 business_card_managentment_system.py
    
    請輸入功能數字: 1
    name:a
    phone:a
    address:a
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}]

    請輸入功能數字: 1
    name:b
    phone:b
    address:b
    [{'name': 'a', 'phone': 'a', 'addr': 'a'}, {'name': 'b', 'phone': 'b', 'addr': 'b'}]

    請輸入功能數字: 5
    name	phone	addr
    a	a	a
    b	b	b

    請輸入功能數字: 4
    name: a
    a	a	a

    請輸入功能數字: 4
    name: b
    b	b	b

    請輸入功能數字: 4
    name: c
    查無此人
    ```
  * 最後把用拿測試的print(business_card)標記掉
    ```python=
    # print
    print("="*10)
    print(" 1.append")
    print(" 2.delete")
    print(" 3.modify")
    print(" 4.inquire")
    print(" 5.end")
    print("="*10)

    # 需要一個列表來儲存名片
    business_card = []
    while True:

        # input
        num = int(input("請輸入功能數字: "))

        # function

        if num == 1:
            new_name = input("name:")
            new_phone = input("phone:")
            new_addr = input("address:")

            new_info = {}
            new_info["name"] = new_name
            new_info["phone"] = new_phone
            new_info["addr"] = new_addr

            business_card.append(new_info)
            #test(print(business_card))

        elif num == 2: # 還沒想到怎麼刪整個{}
            pass

        elif num == 3:
            pass

        elif num == 4:
            find_name = input("name: ")

            flag = False
            for temp in business_card:
                if find_name == temp["name"]:
                    print("%s\t%s\t%s"%(temp["name"], temp["phone"], temp["addr"]))
                    flag = True
                    #break
            if flag == False:
                print("查無此人")

        elif num == 5:
            print("name\tphone\taddr")
            for temp in business_card:
                print("%s\t%s\t%s"%(temp["name"], temp["phone"], temp["addr"]))

        elif num == 6:
            break

        else:
            print("輸入有誤")

        print("") # 空一行
    ```

Traversal ( while & for, 台灣: [尋訪](http://alrightchiu.github.io/SecondRound/binary-tree-traversalxun-fang.html); 中國: [遍歷](https://zh.wikipedia.org/wiki/树的遍历) )
---

```Terminal
$ ipython3

In [1]: a = [1,2,3,4,5,6,7]                                                                             

In [2]: for temp in a: 
   ...:     print(temp) 
   ...:                                                                                                 
1
2
3
4
5
6
7

In [3]: a_lenght = len(a)                                                                               

In [4]: i = 0                                                                                           

In [5]: while i<a_lenght: 
   ...:     print(a[i]) 
   ...:     i+=1                                                                                        
1
2
3
4
5
6
7
```

for_else (只有python可以)
---
```Terminal
$ ipython3

In [1]: a = [1,2,3,4,5]
In [2]: for temp in a: 
   ...:     print(temp) 
   ...: else: 
   ...:     print(6) 
   ...:    
1
2
3
4
5
6
# for 會先循環完再執行else

In [3]: b = []
In [4]: for temp2 in b: 
   ...:     print(temp2) 
   ...: else: 
   ...:     print(6) 
   ...:     
6
# for一樣有執行循環，只是內容是空的，循環玩執行else

In [5]: for temp in a: 
   ...:     print(temp) 
   ...:     break 
   ...: else: 
   ...:     print(6) 
   ...:         
1
# break跳出後，else就沒有再執行了
```
`vi for_else.py`
```python=
# 名片系統找人的另種寫法
a = [{"name":"a", "age":18},{"name":"b", "age":20}]

while True:

    find_name = input("name: ")

    for temp in a:
        if find_name == temp["name"]:
            print(temp)
            break 
            # if 成立時輸出資料，然後直接跳出，就不會執行 else
            # 如果 if 一直到 for 循環完都沒有成立，就沒有任何輸出，也沒有觸發到 break
            # 然後就能接著執行 else
    else: 
        print("查無此人")
```
```Terminal
$ python3 for_else.py

name:  a
a	18
name: b
b	20
name: c
查無此人
```

Tuple ()
---
Tuple只能查，增刪改都不行


Function
---
把具有獨立功能的代碼塊當作一個整體，該整體即為一個Function
`vi def_定義並調用函數.py`
```python=
# 定義函數
def print_card():
    print("="*50)
    print(" Business Card Managentment System ")
    print(" 1.Name")
    print(" 2.Addr")
    print(" 3.Phone")
    print("="*50)

def print_triangle():
    i = 1
    while i <= 5:
        j = 1
        while j <= i:
            print("*",end="")
            j+=1
        print("")
        i+=1

# 調用函數
print_card()
print_triangle()
```
`vi def_帶有參數的函數.py`
```python
def sum_2_number(a,b): # 直接把變量放到裡面
    #a = 1
    #b = 2
    result = a + b
    print("%d + %d = %d"%(a, b, result)) # 1 + 2 = 3

num1 = int(input("請輸入第一個數字："))
num2 = int(input("請輸入第二個數字："))
sum_2_number(num1, num2) # 調用函數時，賦予變量
```

Return的作用-獲取溫度
---

`$ vi return_value_function.py`

```python=
def get_temperature_Celsius():
    temperature_Celsius = 22
    print("當前的攝氏溫度是：%d"%temperature_Celsius)
    
def get_temperature_Fahrenheit():
    temperature_Fahremheit = temperature_Celsius*9/5+32
    print("當前的華氏溫度是：%d"%temperature_Fahremheit)

get_temperature_Celsius()
get_temperature_Fahrenheit()

# temperature_Fahremheit = temperature_Celsius*9/5+32
# NameError: name 'temperature_Celsius' is not defined
# 兩個函數的值不能互相流通
```
`$ vi return_value_function.py`
```python=
def get_temperature_Celsius():
    temperature_Celsius = 22
    print("當前的攝氏溫度是：%d"%temperature_Celsius)
    return temperature_Celsius # 1.將 temperature_Celsius 的值回傳 -> get_temperature_Celsius() = 22

def get_temperature_Fahrenheit(temperature_Celsius): # 4.指定參數
    temperature_Fahremheit = temperature_Celsius*9/5+32
    print("當前的華氏溫度是：%d"%temperature_Fahremheit)

result = get_temperature_Celsius() # 2.定義變量
get_temperature_Fahrenheit(result) # 3.賦予變量

```

多個 Return
---
`vi return2_一個函數中有多個return.py`

```python=
def test():
    a = 1
    b = 2
    c = 3
    return a
    return b
    return c
    
num = test()
print(num)

# python3 return2_一個函數中有多個return.py
# 1 
# 只有回傳a! 
# 因為return會結束function
# 所以return a之後的就都沒有被執行到
```

`vi return2_一個函數中有多個return.py`

```python=
# 解決辦法: 把value包起來傳回去
def test():
    a = 1
    b = 2
    c = 3
    
    d = [a,b,c]
    return d
    #return a
    #return b
    #return c
    
num = test()
print(num)
```

異常處理
---
```python
print(num)
print("--1--")
```
```$
NameError: name 'num' is not defined
```
- 當上面異常時, 直接就結束程序, 導致下面無法執行
- try
```python
try:
    print(num)
except NameError: # NameError 打印 -1-
    print("-1-")

print("-2-")
```
```$
-1-
-2-
```
```python
try:
    #print(num)
    open("xxx.txt")
except NameError:
    print("-1-")
except FileNotFoundError:
    print("-3-")
    
# except (NameError, FileNotFoundError): 
#     print("-4-") 
# 兩句合一, 元祖

print("-2-")
```
```$
-3-
-2-
```
- Exception
```python
try:
    11/0
except (NameError, FileNotFoundError):
    print("-1-")
    
# 異常是其他的: Exception
# as 把異常return出來, 沒有需要就不用寫
except Exception as ret:
    print(ret)

# python2的其他異常表示
# except: -> 沒有Exception

print("-2-")
```
- else, finally
```python
try:
    11/0
except (NameError, FileNotFoundError):
    print("-1-")
except Exception as ret:
    print(ret)
else: # 沒有異常的話輸出-3-
    print("-3-")
finally: # 不論有無異常, 最後都輸出-4-
    print("-4-")

print("-2-")
```
- 異常傳遞
```python
def test1():
    try:
        test2()
    except Exception:
        print("-1-")

def test2():
    print(num)

test1()
```
- 自定義異常
```python
class xxx(Exception): # Exception 所有異常的父類
    def __init__(self, length, atleast):
        self.length = length
        self.atleast = atleast


try:
    psw = input("password:(至少三個半形)")
    if len(psw)<3:
        raise xxx(len(psw), 3)
except xxx as ret:
    print("你只輸入%d, 至少要%d個啦"%(ret.length, ret.atleast))
```
- 異常處理拋出異常
```python
class xxx(object):
    def __init__(self, switch):
        self.switch = switch
    def xxxx(self, a, b):
        try:
            a/b
        except Exception as ret:
            if self.switch:
                print(ret)
            else:
                # 把異常丟還給系統
                raise

t = xxx(True)
t.xxxx(11,0)

print("---")

t = xxx(False)
t.xxxx(11,0)

# 應用:
# 寫LOG日誌, 有意義的異常寫下來, 沒意義的惡意攻擊就丟還給系統處理
```
```$
division by zero
---
ZeroDivisionError: division by zero
```

Python3' Note
===


* 可變類型: List, Dict
* 不可變類型: Num, Str, Tuple
* [Hash function](https://zh.wikipedia.org/wiki/散列函數)
  ```python3=
  In [xx]: a = {[a]:123}
  TypeError: unhashable type: 'list'
  ```
  * 為避免使用者更改 key 而造成 key 與 Hash Value 無法對應，
  * 故 key 不得使用可變類型

[遞歸(Recursion)](https://zh.wikipedia.org/wiki/递归)
---
* 欲完成[階乘](https://zh.wikipedia.org/wiki/階乘)運算 4!
  * 想法一：4! = 4\*3\*2*1
    ```python
    i = 1
    num = 1
    while i<5:
        num *=i
        i+=1

    print(num)
    ```
  * 想法二: 4! = 4 * 3!  
    ```python
    '''概念：

    def xxxx(num):
        num * xxxxx(num-1)

    def xxx(num):
        num * xxxx(num-1)

    def xx(num):
        num * xxx(num-1)

    xx(4)

    每次都乘自己-1的結果
    '''
    
    # 實現
    
    def getnum(num):
        if num>1:
            return num * getnum(num-1)
        else:
            return num

    result = getnum(4)
    print(result)

    '''
    運作: 
    
    getnum(4) = 4 * getnum(3) = 4 * 6
    getnum(3) = 3 * getnum(2) = 3 * 2
    getnum(2) = 2 * getnum(1) = 2 * 1
    getnum(1) = 1
    '''

    # 使用遞歸時注意: 避免死循環
    # 運作死循環的函數時，執行到某一次程式時就會崩潰
    # 因為內存外溢
    ```

匿名函數
---
* 一般函數
  ```python
  def test(a,b):
    # a+b
    return a+b

  result1 = test(1,2)
  print("result=%d"%result1)
  # TypeError: %d format: a number is required, not NoneType
  # 要回傳，否則會報錯
  ```
  
* 匿名函數
  ```python
  # 變量 = lambda 參數:式子
  c = lambda a,b:a+b

  # 調用匿名函數
  result2 = c(1,2)
  print("result=%d"%result2)
  ```

* 兩者區別
  * 區別標準: 匿名函數自帶 return
  * 區別實益: 
    * 一般函數用來寫較複雜的東西,
    * 匿名函數則寫較簡易的東西(如計算).


匿名函數應用
---

```python
In [xx]: apple = [1,2,3,5,3,23,2,25,235,4,234]   
In [xx]: apple.sort()
In [xx]: apple
Out[xx]: [1, 2, 2, 3, 3, 4, 5, 23, 25, 234, 235]
# sort 按大小排序

In [xx]: a = [{"a":"A", "b":22}, {"a":"B", "b":19}, {"a":"C", "b":20}]
In [xx]: a.sort()
TypeError: '<' not supported between instances of 'dict' and 'dict'

In [xx]: a.sort(key= lambda x:x["b"])
# 指定 key 的參數為 x,
# 亦即 x 有 "a" 跟 "b"
# 接著取 "b" 的 value 出來就能比較了
In [xx]: a
Out[xx]: [{'a': 'B', 'b': 19}, {'a': 'C', 'b': 20}, {'a': 'A', 'b': 22}]
```

匿名函數應用2
---

```python
# 舊寫法
def test(a,b):
    result = a+b
    print("Result1=%s"%result)

# 新寫法
def test2(a,b,func):
    result = func(a,b)
    print("Result2=%s"%result)

test(1,2)
test2(1,2, lambda x,y:x+y)
test2(1,2, lambda x,y:x-y)

# 優點: 讓test function更彈性，而不會侷限在一個功能
```

匿名函數應用2延伸
---
```python
# coding=utf-8

def test(a,b,func):
    result = func(a,b)
    print("Result=%s"%result)

new_func = input("請輸入一個匿名函數: ")

test(1,2,new_func)

'''Terminal
$ python2 匿名函數應用延伸.py
請輸入一個匿名函數: lambda x,y:x+y+100
Result=103

$ python3 0511_匿名函數應用延伸.py 
請輸入一個匿名函數: lambda x,y:x+y+100
TypeError: 'str' object is not callable
'''
# python3 的 input 會將輸入數據視為一個str
# 解決辦法: eval
```
```python
# coding=utf-8

def test(a,b,func):
    result = func(a,b)
    print("Result=%s"%result)

new_func = input("請輸入一個匿名函數: ")
new_func = eval(new_func)

test(1,2,new_func)

'''Terminal
$ python3 匿名函數應用延伸.py
請輸入一個匿名函數: lambda x,y:x+y+100
Result=103
'''
```

補充知識點_可變與不可變
---
```python
a = 100
b = [100]
c = [100]

def test(num):
    num+=num
    print(num)

def test2(num):
    num = num + num
    print(num)

test(a)
print(a)
print("---")
test(b)
print(b)
print("---")
test2(c)
print(c)

'''Terminal
200
100
# 遇到不可變時(a,num), 會直接創一個新的變量來儲存(局部變量)
---
[100, 100]
[100, 100]
# 遇到可變時(b,list), 就會直接改(全局變量)
---
[100, 100]
[100]
# num+=num ≠ num=num+num
# num=num+num 是另 num 指向了一個新的id(num+num),而非原本的c
# 故 c 沒被修改
'''


```

補充知識點_交換兩個變量
---

```python
a = 6
b = 4

'''方法一
c = 0
c = a
a = b
b = c
'''

'''方法二
a = a+b
b = a-b
a = a-b
'''

# 方法三
a,b = b,a

print(a,b)
```

str常見操作
---
```python
In [1]: mystr = "dog is dog,not cat."
In [2]: mystr.find("mouse") 
Out[2]: -1
In [3]: mystr.find("dog")
Out[3]: 0
In [4]: mystr.find("cat")
Out[4]: 15
In [5]: mystr.index("mouse")
ValueError: substring not found
In [6]: mystr.index("dog")
Out[6]: 0
In [7]: mystr.index("cat") 
Out[7]: 15
In [8]: mystr.rfind("dog")
Out[8]: 7
In [9]: mystr.rindex("dog")
Out[9]: 7
In [10]: mystr.count("dog") 
Out[10]: 2
In [11]: mystr.count("doggie")
Out[11]: 0

# replace (old, new, count)

In [12]: mystr.replace("is","IS")
Out[12]: 'dog IS dog,not cat.'
In [13]: mystr
Out[13]: 'dog is dog,not cat.'
# str 不可變，故mystr沒有真的被改變，是指向另一個id，
# 如欲保存, 需另用一個變量將其存下
In [14]: mystr.replace("dog","DOG") 
Out[14]: 'DOG is DOG,not cat.'
In [15]: mystr.replace("dog","DOG",1)
Out[15]: 'DOG is dog,not cat.'
In [16]: mystr.replace("dog","DOG",2)
Out[16]: 'DOG is DOG,not cat.'

# split(sep=None, maxsplit=-1) 
In [19]: mystr.split(" ")
Out[19]: ['dog', 'is', 'dog,not', 'cat.']
In [24]: mystr.split(" ", 2)
Out[24]: ['dog', 'is', 'dog,not cat.']

In [56]: mystr.partition("not")
Out[56]: ('dog is dog,', 'not', ' cat.')
In [57]: mystr.partition("dog")
Out[57]: ('', 'dog', ' is dog,not cat.')
In [58]: mystr.rpartition("dog") 
Out[58]: ('dog is ', 'dog', ',not cat.')

In [59]: test2 = "123\n1233234\nasdhjwhkjq\nfdhfjkhfd\n123sff2"
In [61]: test2.splitlines()
Out[61]: ['123', '1233234', 'asdhjwhkjq', 'fdhfjkhfd', '123sff2']

# capitalize & title
In [29]: mystr.capitalize()
Out[29]: 'Dog is dog,not cat.'
In [31]: mystr.title()
Out[31]: 'Dog Is Dog,Not Cat.'

# startswith
In [34]: child_name = "Wang xxx" 
In [35]: child_name.startswith("Wang")
Out[35]: True
In [36]: child_name.startswith("li")
Out[36]: False
# endswith
# 應用: 查檔案類型
In [37]: file_name = "xxx.txt"
In [38]: file_name.endswith("txt")
Out[38]: True
In [39]: file_name.endswith("tnt")
Out[39]: False

# isalpha 判斷str是否為純字母
In [63]: a = "fjkhjkwqhjkh"
In [64]: a.isalpha()
Out[64]: True
In [65]: a = "fjkhjkwqhjkh1"
In [66]: a.isalpha()
Out[66]: False
# isdigit 判斷str是否為純數字
In [70]: b = "123"
In [71]: b.isdigit()
Out[71]: True
'''應用舉例情境
In [75]: num = int(input("請輸入功能數字:"))
請輸入功能數字:1ab
ValueError: invalid literal for int() with base 10: '1ab'
# 用戶如果不是輸入數字，程式就掛了
# 解決辦法: 先判斷用戶是不是輸入你要的再轉，用戶亂輸就print("徹幹礁")
'''
# isalnum 判斷str是不數字與字母組成
# 常用於帳號密碼組成判斷
In [76]: c = "1223fskdjfk"
In [77]: c.isalnum()
Out[77]: True
In [80]: c = "123 jfdks"
In [81]: c.isalnum()
Out[81]: False

# isspace
In [1]: a = "   "
In [2]: a.isspace()
Out[2]: True
In [3]: a = "  _  " 
In [5]: a.isspace()
Out[5]: False

# upper 將所有字都變成大寫
In [xx]: exit_flag = "Yes"
In [42]: exit_flag.upper()
Out[42]: 'YES'
# lower 將所有字都變成小寫
In [43]: exit_flag.lower()
Out[43]: 'yes'
# 應用舉例情境: 如欲使用戶輸入yes來退出程式, 此時用戶可能輸入的yes可能有好幾種(YES,yes,Yes...)
# 解決方法一: 每一種都寫一段程式碼來退出
# 解決方法二: 使用upper / lower 來統一變成大寫/ 小寫
 
In [44]: lyric = "腦海有風, 髮膚無損."
In [48]: lyric.center(20)
Out[48]: '    腦海有風, 髮膚無損.     '
In [49]: lyric.ljust(20)
Out[49]: '腦海有風, 髮膚無損.         '
In [50]: lyric.rjust(20)
Out[50]: '         腦海有風, 髮膚無損.'

# strip 砍空格
In [51]: test = lyric.center(20)
In [52]: test
Out[52]: '    腦海有風, 髮膚無損.     '
In [53]: test.strip()
Out[53]: '腦海有風, 髮膚無損.'
In [54]: test.lstrip()
Out[54]: '腦海有風, 髮膚無損.     '
In [55]: test.rstrip()
Out[55]: '    腦海有風, 髮膚無損.'

# join 在每個str中插入指定的str, 形成一個新的str
In [6]: names = ["apple", "banana", "cow"]
In [7]: a = "_"
In [8]: a.join(names)
Out[8]: 'apple_banana_cow'

# Q
# a = "fdhjsfh sdkjfl\n\n\n jdsf wklj \t\t\t  kqjk jkl jla j  lkjlkqjrlk "
# 欲將 a 的 "space" "\t" "\n" 給砍了
In [10]: a = "fdhjsfh sdkjfl\n\n\n jdsf wklj \t\t\t  kqjk jkl jla j  lkjlkqjrlk "
In [11]: a.split() 
Out[11]: ['fdhjsfh', 'sdkjfl', 'jdsf', 'wklj', 'kqjk', 'jkl', 'jla', 'j', 'lkjlkqjrlk']
In [12]: b = " "
In [13]: b.join(a.split()) 
Out[13]: 'fdhjsfh sdkjfl jdsf wklj kqjk jkl jla j lkjlkqjrlk'
```

讀寫文件
===
```python
In [16]: f = open("haha.txt") 
FileNotFoundError: [Errno 2] No such file or directory: 'haha.txt'

In [17]: f = open("haha.txt", "w")
In [18]: f.write("haha")
Out[18]: 4
In [19]: f.close() # 寫完記得關起來

In [20]: f = open("haha.txt") 
# 沒有報錯 ->已有 haha.txt 可以讀
 
In [22]: f.read(1)
Out[22]: 'h'
In [23]: f.read(1) 
Out[23]: 'a'
In [24]: f.read(1)
Out[24]: 'h'
In [25]: f.read(1) 
Out[25]: 'a'
In [26]: f.read(1) 
Out[26]: ''
In [27]: f.read(1) 
Out[27]: ''
# read 會從上次讀取的地方繼續往後讀
In [29]: f.close() # 讀完記得關起來
```
`vi 隨便寫寫.py`
```python
f = open("hahaha.txt", "w")
f.write("哈哈哈")
f.close()

'''Terminal
$ python3 隨便寫寫.py
$ ls
隨便寫寫.py hahaha.txt
'''
```
`vi 讀取隨便寫寫.py`
```python
f = open("hahaha.txt", "r")

content = f.read()
print(content)

f.close()

'''Terminal
$ python3 讀取隨便寫寫.py
哈哈哈
'''
```
`vi 複製檔案.py`
```python=
old_file_name = input("請輸入欲複製的文件名(含檔名): ")
f_read = open(old_file_name, "r")
content = f_read.read()

new_file = open("xxxx.txt", "w")

new_file.write(content)

f_read.close()
new_file.close()

'''Terminal
$ 複製檔案.py
請輸入欲複製的文件名(含檔名): hahaha.txt
$ ls
隨便寫寫.py 複製檔案.py hahaha.txt xxxx.txt
$ cat xxxx.txt
哈哈哈
''' 
# 檔名有點問題
```
`vi 複製檔案.py`
```python=5
# new_file = open("xxxx.txt", "w")
new_file_name = old_file_name + "[copy]"
new_file = open(new_file_name, "w")

'''Terminal
$ 複製檔案.py
請輸入欲複製的文件名(含檔名): hahaha.txt
$ ls
隨便寫寫.py 複製檔案.py hahaha.txt hahaha.txt[copy] xxxx.txt
'''
# hahaha.txt[copy] 這在win系統無法被正確執行!
```
`vi 複製檔案.py`
```python=5
# new_file = open("xxxx.txt", "w")
# new_file_name = old_file_name + "[copy]"
new_file_name = old_file_name.rreplace(".", "[copy].", 1)
new_file = open(new_file_name, "w")

'''Terminal
$ python3 0703_複製隨便寫寫.py 
請輸入欲複製的文件名(含檔名): hahaha.txt 
AttributeError: 'str' object has no attribute 'rreplace'
$ ipython3
In [xx] a = "xxx"
In [xx] a = r
replace() rjust() rstrip() rfind() rpartition() rindex() rsplit()
'''
```
`vi 複製檔案.py`
```python=5
# new_file = open("xxxx.txt", "w")
# new_file_name = old_file_name + "[copy]"
# new_file_name = old_file_name.rreplace(".", "[copy].", 1)
position = old_file_name.rfind(".")
new_file_name = old_file_name[:position] + "[copy]" + old_file_name[position:]
new_file = open(new_file_name, "w")

'''Terminal
$ 複製檔案.py
請輸入欲複製的文件名(含檔名): hahaha.txt
$ ls
隨便寫寫.py 複製檔案.py hahaha.txt hahaha.txt[copy] xxxx.txt hahaha[copy].txt
$ cat hahaha[copy].txt
哈哈哈
'''
```
```python
In [44]: f = open("hello_world.py")
In [45]: f.read()
Out[45]: '# -*- coding:utf-8 -*-\n\n# 輸出Hello,world\nprint("Hello, world")\n'
In [47]: f.close()

In [48]: f = open("hello_world.py")
In [49]: f.readlines()
Out[49]: 
['# -*- coding:utf-8 -*-\n',
 '\n',
 '# 輸出Hello,world\n',
 'print("Hello, world")\n']
In [51]: f.close()

In [52]: f= open("hello_world.py") 
In [53]: f.readline() 
Out[53]: '# -*- coding:utf-8 -*-\n'
In [54]: f.readline() 
Out[54]: '\n'
In [55]: f.readline() 
Out[55]: '# 輸出Hello,world\n'
In [56]: f.readline()
Out[56]: 'print("Hello, world")\n'
In [57]: f.readline() 
Out[57]: ''
In [58]: f.readline()
Out[58]: ''
```
`vi 複製檔案.py`
```python=
old_file_name = input("請輸入欲複製的文件名(含檔名): ")
f_read = open(old_file_name, "r")


# new_file = open("xxxx.txt", "w")
# new_file_name = old_file_name + "[copy]"
# new_file_name = old_file_name.rreplace(".", "[copy].", 1)
position = old_file_name.rfind(".")
new_file_name = old_file_name[:position] + "[copy]" + old_file_name[position:]
new_file = open(new_file_name, "w")

# content = f_read.read() -> 萬一讀取的檔案超級大石，電腦就會掛掉
# new_file.write(content)

while True:
    content = f_read.read(1024)
    
    if len(content) == 0:
        break

    new_file.write(content)

f_read.close()
new_file.close()
```
```python
In [71]: f = open("0-100_even_numbers.py")
In [72]: cat 0-100_even_numbers.py
a = 1
while a<=100:
    if a%2==0:  # 如果a/2沒有餘數時
        print(a)
    a+=1
    
# read 會從頭開始讀
In [73]: f.read(1)
Out[73]: 'a'
In [74]: f.read(1)
Out[74]: ' '
In [75]: f.read(1)
Out[75]: '='

# tell 會告訴你現在讀到哪
In [78]: f.tell()
Out[78]: 3


# seek(cookie, whence=0, /) 可以指定位置
# Values for whence are:
    # 0 -- start of stream
    # 1 -- current stream position
    # 2 -- end of stream
In [79]: f.seek(0,2)
Out[79]: 89 
In [80]: f.read(1)
Out[80]: '' # 指針已經指到最後了，故後面沒東西了
In [82]: f.seek(0,0)
Out[82]: 0
In [73]: f.read(1)
Out[73]: 'a'
In [74]: f.read(1)
Out[74]: ' '
In [75]: f.read(1)
Out[75]: '='
In [78]: f.tell()
Out[78]: 3
In [88]: f.seek(50,0)
Out[88]: 50
In [89]: f.read(1)
Out[89]: '有'
```
Import os
---
```python
In [xx]: import os

# os.listdir = ls
In [116]: os.listdir 
['xxxx.txt']

# os.rename = mv
In [118]: os.rename("xxxx.txt", "test.txt")
In [116]: os.listdir 
['test.txt']

# os.remove = rm
In [120]: os.remove("test,txt")
In [116]: os.listdir

# os.mkdir = mkdir
In [122]: os.mkdir("哈哈")
In [116]: os.listdir
['哈哈']

# os.getcwd = pwd
In [124]: os.getcwd()
Out[124]: '/Users/xxxxx/Desktop/python'

# open 支援相對路徑與絕對路徑!
In [125]: f = open("../xxxx", "w")
In [134]: f = open("哈哈/xxxx", "w")

# os.chdir = cd
In [xx]: os.chdir("../")
In [124]: os.getcwd()
Out[124]: '/Users/xxxxx/Desktop'
In [116]: os.listdir
['xxxx']
In [xx]: os.chdir("python/哈哈")
In [124]: os.getcwd()
Out[124]: '/Users/xxxxx/Desktop/python/哈哈'
In [116]: os.listdir
['xxxx']
In [xx]: os.remove("xxxx")
In [xx]: os.chdir("../")
In [124]: os.getcwd()
Out[124]: '/Users/xxxxx/Desktop/python'

# os.rmdir = rmdir
In [150]: os.rmdir("哈哈/")
```
`vi 批量重命名.py`
```python=
import os

folder_name = input("請輸入重命名的文件夾：")

file_name = os.listdir(folder_name)

for name in file_name:
    os.rename(name,"[小中夭]")
    
'''Terminal
$ python3 0704_批量重命名.py 
請輸入重命名的文件夾：test
FileNotFoundError: [Errno 2] No such file or directory: '大中天-1.txt' -> '[小中夭]'
$ tree
.
├── test
│   ├── 大中天-1.txt
│   ├── 大中天-2.txt
│   ├── 大中天-3.txt
│   ├── 大中天-4.txt
│   └── 大中天-5.txt
└── 批量重命名.py
'''
# 當前路徑下找不到那些文件
# 方法一: 跳進去改
# 方法二: 指定路徑
```
`vi 批量重命名.py`
```python
import os

folder_name = input("請輸入重命名的文件夾：")

file_name = os.listdir(folder_name)

'''方法一
os.chdir(folder_name)
for name in file_name:
    os.rename(name, "小中夭-" + name)
'''

'''方法二
for name in file_name:
    os.rename("./" + folder_name + "/" + name, "./" + folder_name + "/" + "小中夭-" + name)
    # os.rename(./test/大中天.txt, ./test/小中天-大中天.txt)
'''

# 方法二整理
for name in file_name:
    old_file_name = "./" + folder_name + "/" + name
    new_file_name = "./" + folder_name + "/" + "小中夭-" + name
    os.rename(old_file_name, new_file_name)
```

Class
---
`vi class_basic.py`
```python
#class 類名:
    # 屬性
    # 方法

class Cat: # Class 名建議首字大寫
    # 屬性

    # 方法:
    # def 定義在class裡面稱為方法
    # class 中的方法參數要寫一個參數，用來傳遞當前的對象，常用self
    def eat(self):
        print("貓在吃飯")

    def drink(self):
        print("貓在喝水")

    def introduce(self):
        # print("%s 的年齡是%d"%(tom.name, tom.age))
        print("%s 的年齡是%d"%(self.name, self.age))ff

# 創建一個對象
# 變量 = 執行class -> 執行class時，會在內存開啟一個空間(對象)並返回對象的引用(id)，接著用一個變量指向該引用
tom = Cat()

# 調用對象的方法
tom.eat()
tom.drink()

# 添加屬性
tom.name = "Tom"
tom.age = 100

# 輸出屬性方法一
# print("%s 的年齡是%d"%(tom.name, tom.age))

# 輸出屬性方法二
tom.introduce() # 相當於 tom.introduce(tom)

# 建立另一個對象
meowth = Cat()
meowth.name = "meowth"
meowth.age = 50
meowth.introduce()
'''Terminal
貓在吃飯
貓在喝水
Tom 的年齡是100
Tom 的年齡是100
# 問題出在introduce 的 print 不應取tom！
'''
```
`vi init.py`
```python
class Cat: 
   
    # 初始化對象
    def __init__(self, new_name, new_age):
        # print("------")
        self.name = new_name
        self.age = new_age

    def eat(self):
        print("貓在吃飯")

    def drink(self):
        print("貓在喝水")

    def introduce(self):
        print("%s 的年齡是%d"%(self.name, self.age))

tom = Cat("Tom", 100)
# tom.name = "Tom"
# tom.age = 100
tom.introduce()

meowth = Cat("Meowth")
# meowth.name = "meowth"
# meowth.age = 50
meowth.introduce()

'''Terminal
------
Tom 的年齡是100
------
meowth 的年齡是50

# 創建對象的流程
# ->等號右邊<-
# 1. 創建一個對象
# 2. python 會自動調用 __init__ -> 對象的引用會傳到__init__ -> self 指向該對象來執行 function

# ->等號左邊<-
# 3. 返回創建對象的引用給變數(tom/ meowth)
'''
```