2017年11月4日 星期六

Python輕鬆上手學課堂筆記

一、Python簡介與環境設定

關於Python
l   Python可執行於多平台,用於網頁製作、物聯網、資料分析(大數據、機器學習、深度學習TensorFlow等)等。

下載Python
l   Python 2Python 3版本差異:
Python 2
穩定但支援至2020年後不再開發新功能。
Python 3
持續開發新功能(建議使用此版本)。

安裝Python(建議選擇的選項)
l   勾選Add Python 3.6 to PATH
在命令提示字元輸入python即可使用,而非每次都要輸入 C:\some\place\where\you\have\this\program\installed\python.exe才能使用,若要關閉Python,在命令提示字元輸入quit()即可。
l   勾選Customize installation
選擇安裝位置為C:\Python36

下載Anaconda進行程式開發
l   因為Windows編譯器與macOSLinux不盡相同,必須另外使用第三方的函式庫。

Python如何執行
l   原始碼轉換為位元碼,再轉換為執行期:
原始碼存檔為py檔,如test.py
位元碼存檔為pyc檔,如test.pycPython編譯器會將原始碼轉成位元碼加速執行。
執行期由Python Virtual Machine執行位元碼。
l   互動式Shell,即時看到結果,難以編修程式:
命令提示字元
python
print("Hello World")
à Hello World
exit()
l   從檔案執行Python,無法即時看到結果,容易編修程式:
print("Hello World")存檔為test.py檔,再執行檔案test.py
命令提示字元
# dir
用以確認檔案在根目錄中,才能使用
dir
test.py
à Hello World
exit()

Python內建開發工具:IDLE
l   使用IDLE互動式Shell,與在命令提示字元使用Python相同。
l   使用IDLE File Editor,從檔案執行Python
IDLE
à File à New File
File
à Save As
Run
à Run Module

Python開發工具:PyCharm
l   Project命名並存檔為test,在test上按右鍵,按New,再按Python File,即可開始寫程式,要執行程式時按Run,再按Run

Python開發工具:Sublime Text
l   開始寫程式,要存檔時按File,再按Save,第一次執行程式前先按Tools,再按Build System,再按Python以確認使用Python執行程式,要執行程式時按Tools,再按Build

Python開發工具:Jupyter Notebook
l   用命令提示字元下載,輸入pip install jupyter
l   用命令提示字元啟用,輸入Jupyter notebook,其後命令提示字元都不可以關閉。
l   先按New,再按Python 3,以確認使用Python 3執行程式,即可開始寫程式,要執行程式時按run cell, select below圖示按鈕,要存檔時按File,再按Download as

二、Python物件與資料結構

變數
l   無論數字還是字串,變數皆可以重新賦值,一次只能賦予一值:
a = 10
print(a)
à 10
a = a + a
print(a)
à 20
l   使用del可以刪除變數:
a = 10
print(a)
à 10
del a
print(a)
à NameError
l   如果要交換a, b變數裡面的元素:
a, b = 1, 2
print(a, b)
à 1 2
a, b = b, a
print(a, b)
à 2 1
l   變數名稱限制:
只能是一個字詞。
只能用英文字母、數字和底線。
不能以數字開頭。

數字特性
l   分為整數和浮點數(小數點),其中指數如4E2屬於浮點數:
4E2 = 4*102
2**3 = 23
4**0.5 = 40.5

#
整除、商數取整
print(22//8)
à 2
l   Python 2時,整數除以整數會得到整數,因此3/2不會得到1.5,若要在Python 2避免這種情況:
方法一為指定其中一個數字為浮點數,如3.0/23/2.0
方法二為用函數float()將整數轉為浮點數。
方法三為在Python 2導入Python 3的功能,輸入下列程式碼即可:
from __future__ import division
3/2
l   浮點數顯示位數:
用%n1.n2f控制浮點數顯示位數,n1指浮點數占用格數;n2指小數點後留幾個位數。
print("%1.2f"%(12.345))
à 12.34

換行與多行文字處理
l   創建字串時,可以使用單引號(')或雙引號(")。
l   print()函式:
print("Hello", end = " ")
print("World")
à Hello World
print("Hello", "World")
à Hello World
print("Hello", "World", sep = ", ")
à Hello, World
l   若字串過長,寫程式時可使用\做為換行符號,執行程式時則不換行:
a = "Hello Wo\
rld"
print(a)
à Hello World
l   使用3個單引號(''')或雙引號(""")做多行處理,執行程式時會換行:
a = '''Hello Wo
rld'''
print(a)
à Hello Wo
rld
l   除了使用#,也可使用3個單引號(''')或雙引號(""")做多行注釋。
l   轉義字元(Escape Character)可讓我們輸入一些不太能放在字串裡的字元:
# \n
印出換行
print("Hello\nWorld")
à Hello
World
# \t
印出定位空格
print("Hello\tWorld")
à Hello       World
# \'
印出單引號
print('It\'s Timmy\'s smart phone.')
à It's Timmy's smart phone.
# \"
印出雙引號
print("\"Hello World\"")
à "Hello World"
# \\
印出反斜線
print("\\Hello World\\")
à \Hello World\

字串索引
l   元素位置:
H      E      L      L      O
0      1      2      3      4
-5     -4     -3     -2     -1
a = "HELLO"
print(a[0])
à H
print(a[-1])
à O
l   :來選定起始點或迄點等範圍:
a = "HELLO"
#
取得從第一個索引之後的所有元素
print(a[1:])
à ELLO
#
取到索引為第四個(不包含第四個)的所有元素
print(a[:4])
à HELL
#
取得所有元素
print(a[:])
à HELLO
#
每跳一個元素順向排序for(int i=0; i<len(a); i++)
print(a[::1])
à HELLO
#
每跳二個元素順向排序for(int i=0; i<len(a); i+=2)
print(a[::2])
à HLO
#
每跳一個元素逆向排序for(int i=len(a)-1; i>0; i--)
print(a[::-1])
à OLLEH

字串特性與相關函式
l   可以使用+做字串的連接:
a = "Hello"
a = a + " World"
print(a)
à Hello World
l   可以使用*重複創建同一字串:
a = "Hello World "
print(a*3)
à Hello World Hello World Hello World
l   可以使用函式.upper().lower()將字串轉換成大小寫:
a = "Hello World"
print(a.upper())
à HELLO WORLD
print(a.lower())
à hello world
l   可以使用函式.isupper().islower()檢查字串的大小寫:
print("Hello World".isupper())
à False
print("hello world".islower())
à True
print("HELLO 5566".isupper())
à True
print("3344 5566".islower())
à False
l   可以使用函式.isX()檢查字串:
只含有字母且不是空的,isalpha()方法會返回True
只含有字母和數字且不是空的,isalnum()方法會返回True
只含有數字且不是空的,isdecimal()方法會返回True
只含有空格、定位空格、換行字元且不是空的,isspace()方法會返回True
只含有大寫字母開頭,而後面都是小寫字母的單字,istitle()方法會返回True
l   可以使用函式.startwith().endswith()檢查字串的開頭與結尾:
a = "Hello World"
print(a.startswith("Hello"))
à True
print(a.endswith("World"))
à True
l   可以使用函式.rjust().ljust().center()對齊文字:
a = "Hello World"
print(a.rjust(20))
à          Hello World
print(a.ljust(20))
à Hello World        
print(a.center(20))
à     Hello World    
print(a.rjust(20, "*"))
à *********Hello World
print(a.ljust(20, "*"))
à Hello World*********
print(a.center(20, "*"))
à ****Hello World*****
l   可以使用函式.rstrip().lstrip().strip()刪除文字:
a = "     Hello World     "
print(a.rstrip())
à      Hello World
print(a.lstrip())
à Hello World    
print(a.strip())
à Hello World
# Spam
四個字在strip()裡面的順序沒差
print("SpamHello WorldSpam".strip("mapS"))
à Hello World
l   可以使用函式.split()將字串文字分隔:
a = "Hello World"
#
依照空白(空格、定位空格、換行字元)分隔,會放在List的資料結構
print(a.split())
à ['Hello', 'World']
#
依照o分隔,會放在List的資料結構
print(a.split("o"))
à ['Hell', ' W', 'rld']
l   可以使用函式.join()將字串文字連接:
print(" Poor ".join(["Hello", "World"]))
à Hello Poor World
l   可以使用函式len()檢查字串的長度:
a = "Hello World"
print(len(a))
à 11
l   可以使用函式dir()做功能的查詢:
a = "Hello World"
# a
是字串,所以dir()列出所有字串a可以用的函式
print(dir(a))
à ['__add__', '__class__', '__contains__',…

使用%s%rrrepr()印出格式化的字串
l   %sstr()%rrepr(),在Python中皆可用做字串的轉換:
a = "Hello World"
print("Here is a number: %s. Here is a string: %s."%(123, a))
à Here is a number: 123. Here is a string: Hello World.
print("Here is a number: %r. Here is a string: %r."%(123, a))
à Here is a number: 123. Here is a string: 'Hello World'.
l   使用r取得raw string
a = r"\n\t this is a \t line with format \t\n"
print(a)
à \n\t this is a \t line with format \t\n
l   使用repr()取得string中的表示:
a = repr("\n\t this is a \t line with format \t\n")
print(a)
à '\n\t this is a \t line with format \t\n'

使用.format()印出格式化的字串
l   根據樣式替代字串:
print("Object 1: {a}, Object 2: {b}, Object 3: {c}".format(a = 1, b = "Hi", c = 12.3))
à Object 1: 1, Object 2: Hi, Object 3: 12.3
l   根據位置替代字串,比起%s,這是比較好控制輸出格式的方法:
print("Object 1: {0}, Object 2: {1}, Object 3: {0}".format("Hello World", "Hi"))
à Object 1: Hello World, Object 2: Hi, Object 3: Hello World

資料轉換int()float()str()min()max()
l   轉為整數int()、轉為浮點數float()、轉為字串str()
print(int(21.6))
à 21
print(int(float("21.6")))
à 21
print(str(21) + " Years Old")
à 21 Years Old
l   最小值min()、最大值max()
print(min(5, 10))
à 5
print(max(5, 10))
à 10

資料輸入input()
l   使用input()函式取得輸入,使用者輸入內容是返回字串,就算使用者輸入的是數字也一樣:
a = input("How are you? ")
print(a)
à How are you? Fine, thank you.
# Fine, thank you.
為自己任意輸入的文字
Fine, thank you.

List:串列,Python常見的資料結構之一
l   其他語言都有陣列(Array)的概念,PythonList比較接近於ArrayList,一個容器可放多個值、多個不同類型的物件。
l   宣告List的方式:
a = ["Hello World", 123, 12.3, "Hi"]
print(a)
à ['Hello World', 123, 12.3, 'Hi']
# len()
用以表示有多少筆資料
print(len(a))
à 4

List索引
l   元素位置:
5      6      7      Hi
0      1      2      3
-4     -3     -2     -1
a = [5, 6, 7, "Hi"]
print(a[-4])
à 5
print(a[3])
à Hi
#
沒位置為4的值,印到位置為3的值
print(a[2:4])
à [7, 'Hi']
print(a[2:])
à [7, 'Hi']
print(a[::2])
à [5, 7]
print(a[::-1])
à ['Hi', 7, 6, 5]
#
假如List中有重複一樣的值,返回第一個找到的元素位置
print(a.index("Hi"))
à 3
b = [[0, 1, 2], [3, 4, 5]]
print(b[1][2])
à 5
l   元素增減、排序:
a = [5, 6, 7, "Hi"]
#
刪減排序在最後的元素
a.pop()
print(a)
à [5, 6, 7]
#
刪減特定的元素,假如串列中有重複一樣的值,刪除第一個找到的值
a.remove(7)
print(a)
à [5, 6]
#
新增元素並排序在最後
a.append(4)
print(a)
à [5, 6, 4]
#
新增元素並指定排序位置
a.insert(1, 7)
print(a)
à [5, 7, 6, 4]
#
數字從小到大排序,若數字與字串混合不可排序
a.sort()
print(a)
à [4, 5, 6, 7]
#
反轉排序
a.reverse()
print(a)
à [7, 6, 5, 4]
l   英文字母元素排序:
a = ["B", "a", "b", "A"]
#
對字串排序時是依照ASCII字串順序來排的
a.sort()
print(a)
à ['A', 'B', 'a', 'b']
#
以一般字典順序來排序
a.sort(key = str.lower)
print(a)
à ['A', 'a', 'B', 'b']
#
反轉排序
a.sort(reverse = True)
print(a)
à ['b', 'a', 'B', 'A']

List其它操作
l   套用List於字串中:
a = list("Hello World")
print(a)
à ['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']
#
字母e存在於字串a
print("e" in a)
à True
#
字母a不存在於字串a
print("a" in a)
à False
l   參照(Assignment),原因請參考「物件的可變性與不可變性」:
a = [5, 6, 7]
b = a
print(a)
à [5, 6, 7]
print(b)
à [5, 6, 7]
a[1] = 2000
print(a)
à [5, 2000, 7]
print(b)
à [5, 2000, 7]
l   複製List解決方法:
a = [5, 6, 7]
import copy
#
如果List內含有List,必須使用copy.deepcopy()函式處理
b = copy.copy(a)
print(a)
à [5, 6, 7]
print(b)
à [5, 6, 7]
a[1] = 2000
print(a)
à [5, 2000, 7]
print(b)
à [5, 6, 7]

Dictionary:字典,Python常見的資料結構之一
l   宣告Dictionary的方式:
# key
為唯一不重複值,若重複,後者會覆蓋前者
dic = {key: value}
l   a = {"E": "Emerald", "LG": "LeafGreen"}
print(a.items())
à dict_items([('E', 'Emerald'), ('LG', 'LeafGreen')])

Dictionary索引
l   元素位置:
a = {"b": 123, "c": "Hi", "d": 12.3}
print(a)
à {'b': 123, 'c': 'Hi', 'd': 12.3}
#
取得keys
print(a.keys())
à dict_keys(['b', 'c', 'd'])
#
取得values
print(a.values())
à dict_values([123, 'Hi', 12.3])
# "b" in a
等同於"b" in a.keys()
print("b" in a)
à True
#
取得單一key所對到的內容(無預設值,比較不推薦)
print(a["b"])
à 123
print(a["e"])
à KeyError
#
取得單一key所對到的內容(有預設值,比較推薦)
print(a.get("b"))
à 123
print(a.get("e"))
à None
#
取得單一key所對到的內容(自設預設值為"Default"
print(a.get("b", "Default"))
à 123
print(a.get("e", "Default"))
à Default
l   元素增減、更新,方法一:
a = {"b": 123, "c": "Hi", "d": 12.3}
#
增加資料到字典中
a["e"] = "New"
print(a)
à {'b': 123, 'c': 'Hi', 'd': 12.3, 'e': 'New'}
#
更新字典內的元素
a["c"] = "New"
print(a)
à {'b': 123, 'c': 'New', 'd': 12.3, 'e': 'New'}
#
刪除字典內的元素
del a["d"]
print(a)
à {'b': 123, 'c': 'New', 'e': 'New'}
l   元素增減、更新,方法二:
a = {"b": 123, "c": "Hi", "d": 12.3}
#
增加資料到字典中
a.update({"e": "New"})
print(a)
à {'b': 123, 'c': 'Hi', 'd': 12.3, 'e': 'new'}
#
更新字典內的元素
a.update({"c": "New"})
print(a)
à {'b': 123, 'c': 'New', 'd': 12.3, 'e': 'New'}
#
刪除字典內的元素
a.pop("d")
print(a)
à {'b': 123, 'c': 'New', 'e': 'New'}
l   setdefault()方法:
a = {"b": 123, "c": "Hi", "d": 12.3}
#
如果key不存在字典中,此方法會設定該鍵的值
a.setdefault("e", 1.23)
print(a)
à {'b': 123, 'c': 'Hi', 'd': 12.3, 'e': 1.23}
#
如果key存在字典中,此方法不會設定該鍵的值
a.setdefault("c", "Hello")
print(a)
à {'b': 123, 'c': 'Hi', 'd': 12.3, 'e': 1.23}

Tuple:多元組,Python常見的資料結構之一
l   Tuple內的值無法被更改,在記憶體中也有固定大小,因此當使用者希望資料能維持一致性,而內容值不能被修改時,例如資料庫回傳資料,可以使用Tuple
l   宣告Tuple的方式:
a = (1, 2, 3)
b = 4, 5, 6
print(a, b)
à (1, 2, 3) (4, 5, 6)
#
如果Tuple內只有一個值的宣告方式
c = (7, )
print(c)
à (7,)
# len()
用以表示有多少筆資料
print(len(a))
à 3
l   Tuple的特性-不變性Immutability
a = ("one", 2, 3.0)
a[0] = "change"
à TypeError
a.append("new")
à AttributeError
l   ListTuple轉換型別:
a = ["Hello", "World"]
print(tuple(a))
à ('Hello', 'World')
b = ("Hello", "World")
print(list(b))
à ['Hello', 'World']

Tuple索引
l   元素位置:
a = ("one", 2, 3.0)
print(a[0])
à one
print(a[-1])
à 3.0
#
假如Tuple中有重複一樣的值,返回第一個找到的元素位置
print(a.index("one"))
à 0
#
計算資料出現次數
print(a.count("one"))
à 1

Set集合
l   當要從兩堆資料中找到之間的相同處與相異處時可以使用集合,如交集、聯集、差集。
l   建立集合:
a = set()
#
使用add()增添資料
a.add(1)
print(a)
à {1}
a.add(2)
print(a)
à {1, 2}
l   可以將一個List轉為Set
a = [1, 1, 2, 2, 3, 4, 5, 6, 1, 1]
print(set(a))
à {1, 2, 3, 4, 5, 6}
l   Set的操作:
a = set([1, 2, 3, 4])
#
聯集
print(a.union(set([3, 5])))
à {1, 2, 3, 4, 5}
#
交集
print(a.intersection(set([3, 5])))
à {3}
#
差集印出a獨有的元素
print(a.difference(set([3, 5])))
à {1, 2, 4}
#
確認a是否是母集合
print(a.issuperset(set([1, 2, 3])))
à True
#
確認a是否是子集合
print(a.issubset(set([2, 3, 4])))
à False

三、Python運算式與陳述

Python中使用運算式
l   比較大小、比較是否相同:
a = 5
b = 3
print(a > b)
à True
print(b > a)
à False
print(a == b)
à False
print(a != b)
à True
c = a == b
print(c)
à False
#
使用notTrue會變成FalseFalse會變成True
print(not c)
à True
l   文字與數字的相等運算:
print(21 == "21")
à False
print(21 == 21.0)
à True
l   布林運算子(not, and, or)Python會先對not運算子運算,然後是and,再來是or
print(not True)
à False
print(not False)
à True
print(True and True)
à True
print(True and False)
à False
print(False and True)
à False
print(False and False)
à False
print(True or True)
à True
print(True or False)
à True
print(False or True)
à True
print(False or False)
à False
l   增強型指定運算子:
a += 1
等同於a = a + 1
a -= 1
等同於a = a - 1
a *= 1
等同於a = a * 1
a /= 1
等同於a = a / 1
a %= 1
等同於a = a % 1

Python中使用陳述式
l   使用:表陳述式,下一行必須使用縮排(Indent),但沒有強制要按多少空白鍵做為縮排。
l   陳述式範例:
a = 5
b = 3
if a > b:
    print("Hello World")
à Hello World
l   程式縮排(Indentation)
使用tab,但是不建議,因為有時候1tab代表4個、6個,或8個等不一定數量的空白鍵。
建議使用空白鍵去區隔執行區塊,以替代其他程式傳統的{}
Pep8
規定使用4個空白鍵(建議)。
Google
規定使用2個空白鍵。

If, Elif, Else
l   if True:
    print("It was true!")
à It was true!
a = False
if a:
    print("It was true!")
else:
    print("It wasn't true!")
à It wasn't true!
l   a = "Bank"
if a == "Auto Shop":
    print("Welcome to the Auto Shop!")
elif a == "Bank":
    print("Welcome to the Bank!")
à Welcome to the Bank!
else:
    print("Where are you?")

Switch…Case
l   Python沒有Switch…Case,但可以使用字典模擬:
# def
定義函式
def func(a):
    # return
回傳結果
    return{"v1": "product 1", "v2": "product 2"}.get(a, "product 3")
a = "v3"
print(func(a))
à product 3

For迴圈(For Loop)
l   印出每一個單字:
for a in "Hello World":
    print(a)
à H

d
l   印出List中的每個元素:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
for b in a:
    print(b)
à 1

10
l   印出Tuple中每個元素:
a = (1, 2, 3)
for b in a:
    print(b)
à 1
2
3
l   印出List中每個Tuple,再印出Tuple中第一個元素:
a = [(2, 4), (6, 8), (10, 12)]
for b in a:
    print(b)
à (2, 4)
(6, 8)
(10, 12)
# Unpacking
for (b1, b2) in a:
    print(b1)
à 2
6
10
l   印出Dictionary中每一個KeyValue
a = {"k1": 1, "k2": 2, "k3": 3}
# print key
for b in a:
    print(b)
à k1
k2
k3
# print value
for b in a:
    print(a[b])
à 1
2
3
# print key, value
for k, v in a.items():
    print(k, v)
à k1 1
k2 2
k3 3
l   使用range()印出每個元素:
#
若使用range(30)會印出029,若使用range(3, 30)會印出329
for a in range(3, 30, 5):
    print(a)
à 3
8
13
18
23
28

While迴圈(While Loop)
l   讓機器人有限次重複執行同樣的動作,功能同For迴圈:
x = 0
while x < 10:
    print("x is currently:", x)
    x += 1
print("All Done!")
à
x is currently: 0

x is currently: 9
All Done!
l   讓機器人無限次不斷重複執行同樣的動作,while True會被執行,while False不會被執行:
# 0
0.0""(空字串)會被判定為False
a = ""
while not a:
    print("Enter Anything")
    a = input()
l   絕對不能執行無窮迴圈程式碼:
while True:
    print("Infinite Loop")

迭代器(Iterator)
l   如果要一一取出內容物件,使用iter()next()
a = [1, 2, 3, 4, 5]
b = iter(a)
print(next(b))
à 1
print(next(b))
à 2
l   固定元素傳入迭代器:
a = [1, 2, 3, 4]
b = ["Hello", "Poor", "World"]
c = [3.14159, 2.71828]

#
方法一,載入套件
from itertools import chain
for ele in chain(a, b, c):
    print(ele, end = ", ")

"""
#
方法二,自訂函式
def testChain(*iterables):
    for ite in iterables:
        for ele in ite:
            yield ele
for ele in testChain(a, b, c):
    print(ele, end = ", ")
"""

Break, Continue, Pass
l   break用以暫停迴圈。
continue
用以直接返回迴圈部分持續執行程式。
pass
用以略過這一迴圈,繼續往下執行程式。
l   測試breakcontinue
x = 0
while x < 10:
    print("x is currently:", x)
    x += 1
    if x == 3:
        print("breaking:", x)
        break
    else:
        continue
        print("continuing…")
à
x is currently: 0
x is currently: 1
x is currently: 2
breaking: 3
l   測試breakpass
x = 0
while x < 10:
    print("x is currently:", x)
    x += 1
    if x == 3:
        print("breaking:", x)
        break
    else:
        pass
        print("continuing…")
à
x is currently: 0
continuing...
x is currently: 1
continuing...
x is currently: 2
breaking: 3

四、Python方法與函式

Python函式
l   使用help()dir()查詢:
import sys
#
使用help查詢套件內容
help(sys)
#
使用dir查詢可用方法
print(dir(sys))
#
不確定該方法的功能,可以使用help查詢
help(sys.exit)
l   希望能寫一次,但在不同情境可以重複呼叫好幾次:
def say_hello():
    print("Hello World")
say_hello()
à Hello World
def add_num(a, b):
    return a + b
print(add_num(1, 4))
à 5
print(add_num("Hello ", "World"))
à Hello World
print(add_num("One", 4))
à TypeError
l   *代表可以接受多個參數:
def add_num(a, *args):
    b = a
    for c in args:
        b += c
    return b
print(add_num(1, 2, 3, 4, 5))
à 15
l   **代表可以接受多個Key/Value參數:
def two_lists(**kvargs):
    keys, values = [], []
    for k, v in kvargs.items():
        keys.append(k)
        values.append(v)
    return [keys, values]
print(two_lists(David = "M", Mary = "F", John = "M"))
à
[['David', 'Mary', 'John'], ['M', 'F', 'M']]

Lambda函式(Lambda Expression)
l   Lambda可以使用單一陳述句建立簡單匿名函式,簡單方便,用完即丟。
l   一般函式與Lambda函式範例:
#
一般函式
def square(a): return a**2
print(square(2))
à 4
# Lambda
函式
square = lambda a: a**2
print(square(2))
à 4
l   是否為偶數:
even = lambda a: a%2 == 0
print(even(3))
à False
print(even(4))
à True
l   取第一個元素:
first = lambda a: a[0]
print(first("Hello World"))
à H
l   字串倒排:
reverse = lambda a: a[::-1]
print(reverse("Hello World"))
à dlroW olleH
l   兩個元素相加:
add = lambda a, b: a + b
print(add(2, 3))
à 5

巢狀陳述與變數範圍(Nested Statement and Scope)
l   Python中每個變數都存在各自的命名空間(Namespace),不同命名空間變數的可視範圍皆不相同,程式會依照LEGB的順序,在不同的可視範圍搜尋變數:
1. Local
2. Enclosing Functions
3. Global (
模組)
4. Built-in (Python)
l   name = "Global Name"
def greet():
    name = "World"
    def hello():
        print("Hello " + name)
    hello()
greet()
à Hello World
print(name)
à Global Name
print(len)
à <built-in function len>
l   讓區域變數(Local)變成全域變數(Global)
x = 50
def func():
    global x
    print("Original x:", x)
    x = 2
    print("Changed x:", x)
print("Before calling func(), x =", x)
à Before calling func(), x = 50
func()
à Original x: 50
Changed x: 2
print("After calling func(), x =", x)
à After calling func(), x = 2

錯誤與例外(Errors and Exceptions)
l   讀取檔案範例,詳見Readingand Writing Files
try:
    with open("testfile", "r") as f:
        print(f.read())
except FileNotFoundError:
    print("Error: Could Not Find File or Read Data")
l   除以0的時候的處理:
dividend = input("Dividend: ")
divisor = input("Divisor: ")
try:
    print(float(dividend) / float(divisor))
except ZeroDivisionError as detail:
    print("ZeroDivisionError", detail)
#
無論執行成功或失敗,最後都要執行的動作,就用finally
finally:
    print("All Done!")
l   不只除以0,除以字串的時候也是錯誤,要如何處理:
dividend = input("Dividend: ")
divisor = input("Divisor: ")
try:
    print(float(dividend) / float(divisor))
except:
    print("Error")
finally:
    print("All Done!")

五、Python物件導向程式設計

Python所有東西都是物件(Object)
l   Python是物件導向語言(Object Oriented Programming Language),每個物件都有Id(檢視唯一的識別碼)、Type(檢視物件的類型),以及Value
a = 1
print(id(a))
à 1573349504
print(type(a))
à <class 'int'>
print(a)
à 1
l   常見的資料型態:
print(type(1))
à <class 'int'>
print(type(()))
à <class 'tuple'>
print(type([]))
à <class 'list'>
print(type({}))
à <class 'dict'>

物件的可變性與不可變性
l   整數、浮點數、字串、多元組(Tuple)屬於不可變型態,當物件不再被使用時,Python會自動做垃圾收集(Garbage Collection)釋放記憶體空間:
a = 1
#
此時a會改連結到21會被自動回收
a = 2
l   串列(List)與字典(Dictionary)屬於可變型態:
a = [1, 2]
a.append(3)
#
此時a[1]會改連結到2002會被自動回收
a[1] = 200
l   兩組不可變的資料,資料內容相同時,會對應到同id
a = 1
b = 1
print(id(a), id(b))
à 1571907712 1571907712
l   兩組可變的資料,即使資料內容相同,會對應到各自的id
a = [1, 2, 3]
b = [1, 2, 3]
print(id(a), id(b))
à 47973720 47974920
l   Python在變數必須存放可變資料型別的值時,會使用參照來處理,例如串列(List)、字典(Dictionary)Python在變數必須存放不可變資料型別的值時,會使用這些值的本身,例如整數、浮點數、字串、多元組(Tuple)

類別(Class)、物件屬性(Object Attribute)、類別屬性(Class Attribute)
l   使用者可以使用class定義自己的類別,進而指派自定義類別至變數以建立實例(Instance)
class Sample(object):
    # pass
代表這裡面不包含任何屬性與方法的定義
    pass
x = Sample()
print(type(x))
à <class '__main__.Sample'>
l   物件包含屬性(Attribute)與方法(Method),使用者可以在類別中使用def __init__()定義建構子以建立物件:
屬性:物件的特性
方法:對物件的操作
l   定義物件屬性範例:
class Dog(object):
    def __init__(self, a):
        #
定義物件屬性,self代表指向實例本身
        self.breed = a
sam = Dog(a = "Lab")
frank = Dog("Huskie")
print(sam.breed)
à Lab
print(frank.breed)
à Huskie
l   定義類別屬性範例:
class Dog(object):
    #
定義類別屬性,類別屬性是公開的
    species = "mammal"
    def __init__(self, a, b):
        #
定義物件屬性
        self.breed = a
        self.name = b
sam = Dog("Lab", "Sam")
print(sam.breed)
à Lab
print(sam.name)
à Sam
print(sam.species)
à mammal
print(Dog.species)
à mammal

方法(Method)
l   類別內的方法是封裝(Encapsulation)的重要概念,可以想成是針對物件屬性與類別屬性的操作。
l   DRY原則:Don't Repeat Yourself,同樣的動作應該被放置於Function中,同樣的Function應該被放置於Class中。
l   class Circle(object):
    pi = 3.14
    def __init__(self, radius = 1):
        self.radius = radius
    def area(self):
        return self.radius * self.radius * Circle.pi
    def setRadius(self, radius):
        self.radius = radius
    def getRadius(self):
        return self.radius
a = Circle()
#
或是使用a = Circle(2)皆可
a.setRadius(2)
#
或是使用print(a.radius)皆可
print(a.getRadius())
à 2
print(a.area())
à 12.56

特殊方法(Special Method)
l   每個物件都有基本的特殊方法如:__init__()__str__()__len__()以及__del__(),這些特殊方法通常都以底線包覆,在定義類別時可以修改這些特殊方法。
l   class Book(object):
    def __init__(self, title, author, pages):
        print("A book is created.")
        self.title = title
        self.author = author
        self.pages = pages
    def __str__(self):
        return "Title: %s, Author: %s, Pages: %s"%(self.title, self.author, self.pages)
    def __len__(self):
        return self.pages
    def __del__(self):
        print("A book is deleted.")
book = Book("Machine Learning with R Cookbook", "David Chiu", 442)
à
A book is created.
print(book)
à
Title: Machine Learning with R Cookbook, Author: David Chiu, Pages: 442
print(len(book))
à 442
del book
à A book is deleted.

如何實作繼承(Inheritance)
l   當要建立的新類別與已經存在的類別有許多共通的屬性與方法,可以繼承該已存在類別,優點為重用(Reuse)已存在的程式碼,並且降低程式的複雜度,其中被繼承者的類別稱為父類別(Superclass),繼承者的類別稱為子類別(Subclass)
l   建立Dog類別繼承Animal類別:
class Animal(object):
    def __init__(self):
        print("Animal Created")
    def who(self):
        print("Animal")
    def eat(self):
        print("Eating")
a = Animal()
à Animal Created
a.who()
à Animal
a.eat()
à Eating
class Dog(Animal):
    def __init__(self):
        #
呼叫Animal的建構子
        Animal.__init__(self)
        print("Dog Created")
    def who(self):
        print("Dog")
    def bark(self):
        print("Woof!")
d = Dog()
à Animal Created
Dog Created
d.who()
à Dog
d.eat()
à Eating
d.bark()
à Woof!

六、Python模組與套件

模組(Module)
l   模組就是以.py做為副檔名的Python程式檔,通常模組內包覆多組函式可供使用者使用,使用者可以透過Import指令匯入模組,而所有模組只會被載入一次,重複Import不會導致函式重複被宣告。
l   內建模組:
import math
#
大於2.4最接近的整數
print(math.ceil(2.4))
à 3
#
探索模組內容物
print(dir(math))
à ['__doc__', '__loader__', '__name__',…
help(math.ceil)
à Help on built-in function ceil in module math:…
l   使用者可以自己開發模組,只要將模組定義為<module>.py,之後便可以透過import <module>來使用模組。
l   自定義模組(User-Defined Module)
#
檔案test.py的程式碼
a = "Hello World"
def hello(name):
    return "Hello, " + name
#
檔案test2.py的程式碼,確認test.pytest2.py在同一個目錄後,執行test2.py
import test
print(test.a)
à Hello World
print(test.hello("Timmy"))
à Hello, Timmy
print(dir(test))
à ['__builtins__', '__cached__', '__doc__',…

模組命名空間(Module Namespace)
l   假設模組一跟模組二都有.hello這個函式,Python可以使用命名空間來避免衝突,但函式若發生衝突,新引入的函式會覆蓋舊的函式。
l   模組引入的方式:
#
檔案test.py的程式碼
a = "Hello World"
def hello(name):
    return "Hello, " + name
#
檔案test2.py的程式碼,確認test.pytest2.py在同一個目錄後,執行test2.py
#
最安全的存取方式
import test
print(test.hello("Timmy"))
à Hello, Timmy
#
有跟hello名字衝突的風險
from test import hello
print(hello("Timmy"))
à Hello, Timmy
#
取個別名h,有跟h名字衝突的風險
from test import hello as h
print(h("Timmy"))
à Hello, Timmy
#
把所有程式都引入,是最不推薦的方法
from test import *
print(a)
à Hello World

套件(Package)
l   多個模組組成一個套件,而套件就是目錄而已,必須在目錄下加上__init__.py來啟用套件。
l   # 套件child的模組
child/
    __init__.py
    test.py
#
檔案test.py的程式碼
a = "Hello World"
def hello(name):
    return "Hello, " + name
#
檔案test2.py的程式碼,確認套件childtest2.py在同一個目錄後,執行test2.py
#
呼叫方法一
from child import test
print(test.hello("Timmy"))
à Hello, Timmy
#
呼叫方法二,必須先在__init__.py內輸入from .test import *
import child
print(child.test.hello("Timmy"))
à Hello, Timmy
#
呼叫方法三
from child.test import hello
print(hello("Timmy"))
à Hello, Timmy
l   __init__.py可以使用__all__限制匯入模組:
#
套件child的模組
child/
    __init__.py
    test.py
#
檔案__init__.py的程式碼
__all__ = ["test"]
#
檔案test.py的程式碼
a = "Hello World"
def hello(name):
    return "Hello, " + name
#
檔案test2.py的程式碼,確認套件childtest2.py在同一個目錄後,執行test2.py
from child import *
print(dir())
à …'__package__', '__spec__', 'test']

如何引用、安裝第三方套件
l   例如Flask 0.12.2套件,選擇下載Flask-0.12.2.tar.gz (md5),以後可對原始碼進行編譯:
https://pypi.python.org/pypi/Flask
l   下載原始碼、解壓縮後,在命令提示字元找到setup.py所在的目錄處執行:
python setup.py install
l   套件管理工具:
easy_install
是內建的,不支援反安裝套件。
pip
是主流套件管理工具,支援反安裝套件。

命令提示字元pip操作
l   requests套件安裝:pip install requests
l   requests套件升級:pip install -U requests
l   requests套件移除:pip uninstall requests
l   requests套件搜尋:pip search requests
l   列出pip說明:pip help
l   列出所有已安裝套件:pip freeze
l   使用者建立套件安裝需求檔requirements.txtpip freeze > requirements.txt
l   其他人可以讀取套建安裝需求檔requirements.txt安裝所列之第三方套件:pip install -r requirements.txt

沒有留言:

張貼留言