PythonBasic_2
Python 基礎語法
前言 - 程式的組成
- 我們先來認識所謂「程式」的基礎,任何程式語言必備的元素有:
- 程式的組成
- 變數
- 基本資料型態
- 如: 整數、浮點數、字串、布林
- 如: 串列、元組、字典、集合等
- 格式化的輸出與輸入
- 如: print(), input()
- 運算子、運算式與敘述
- 如: 加減乘除
- 如: 大小等於
- 選擇性敘述
- 如: if-else
- 迴圈
- 如: for, while
- 進階程式的組成
- 函數fucntion
- 如: def my_function():
- 類別
- 如: class MyClass():
認識 Python
語法簡潔但不失優雅,以及 Python 龐大的生態環境可在不同領域都發揮作用所帶來的便利。
Python 是動態語言(dynamic language)
- 變數使用前不必宣告其資料型態,增加程式設計便利性,缺點是需要在底層判斷變數型別,較耗時。
Python 是直譯語言
- 執行前不必經過編譯(compile)的過程,而是使用直譯器(interpreter)直接直譯與執行,或稱腳本語言(scripting language)。
- 靜態語言如:C、C++、JAVA;動態語言如:Python、JavaScript、Ruby。
Why Python?
- 活躍的社群
- 開放原始碼
- 眾多第三方資源
- 可快速打造產品原型的工具
- 工程師的第二個程式語言
Python 的魅力:
- 語法簡潔但不失優雅,以及 Python 龐大的生態環境可在不同領域都發揮作用所帶來的便利。
Python 變數與基本運算
變數
- Python變數正確來說是資料內容的「標籤」,變數不是盒子。
- 物件先存在,所以說是「變數x被指派給(assigned to) something」比較精確。
- 命名不能與關鍵字重複,自訂義的命名也不要跟引入的模組重複。
變數命名原則
- 開頭可以是: 英文字母、
_
底線)或中文字,支援UTF-8
編碼,大小寫敏感。 - 開頭不能是:數字。
- 要避開Python關鍵字:
and, as, assert, break, class, continue, def, del, elif, else, except,
False, finally, for, from, global, if, import, in, is, lambda, None,
nonlocal, not, or, pass, raise, return, True, try, while, with, yield - 建議避開Python 函數名稱,會覆蓋功能。
- 如果變數需要超過兩個英文單字表達,可用
_
底線連結,或是駝峰型如: MyName 或 myName。my_name = 9527
MyName = 9527
myName = 9527 - 類別的命名依 PEP8,建議為"大寫駝峰"命名,如
MyClass
。class MyClass():
pass - 命名函式依 PEP8,以小寫及底線連結 (如:
my_function
)。def my_function():
return result
- 模組命名與保護,通常引入模組可以用的方式
import foo
from foo import *
import foo as fo
from foo import qoo as qo - 要保護 module 變數或函式不被
from foo import *
- 在名稱前底線
_
,例如除非用from foo import _var
呼叫,才能使用_var
模組 。
- 在名稱前底線
- 要保護類別的 private 變數或方法,名稱前加上兩個底線
__
,如MyClass.__my_private_module
,才能呼叫該私有變數或方法,但不夠嚴謹。
便利貼 = "水壺"
#錯誤示範-數字不能當命名開頭
9527_is_good = '多拉a夢'
基本資料型態
整數 int
- Python的int依記憶體可放無限制整數,不易溢位(overflow)。
- C語言int佔4個位元組,取值範圍-2147483648~+2147483647,超過範圍會溢位。
浮點數 float
- 有小數點的數字,Python運算會簡易判斷自動轉換。
- 由於電腦是以二進位的數值組合,轉換為十進位的浮點數會有誤差,依IEEE 754實作。
- 轉換二進位用
bin()
,在Python中為0b
開頭的數字,如0b1101。 - 轉換八進位用
oct()
,在Python中為0o
開頭的數字,如0o61。 - 轉換十六進位用
hex()
,在Python中為0x
開頭的數字,如0x5D。
- 轉換二進位用
布林 Boolean
- 經條件判斷後,回傳結果為
True
或False
int(True)
回傳1;int(False)
回傳0。
type(True)
type(int(True))
int(False)
字串 String
- 以單引號(
'
)或雙引號("
)前後括起來的任意輸入文字。 - 如果文句中有單/雙引號,則應以雙/單引號避免錯誤。
- 超過一行的字串以3個單引號或3個雙引號包夾
- 不想換行的分段輸入,在程式行末增加
\
符號
print("Hello World")
print('Hello World')
print('I love "eat" !')
print("I love 'eat' !")
"""ghghghjhjhjlhjk
jkjkjkjkj"""
#會因程式換行以致輸出結果換行
"""
我是胖虎,我是孩子王
我是胖虎,我是孩子王
"""
#輸出結果不會換行的方式,行末增加"\"
'''\
我是胖虎,我是孩子王\
我是胖虎,我是孩子王\
'''
逸出字元(Escape Character)
逸出字元 | 意義 |
---|---|
\' | 顯示出單引號 |
\" | 顯示出雙引號 |
\\ | 顯示出反斜線 |
\n | 換行 |
\t | tab |
檢查資料型態
type()
轉換資料型態
- 轉為文字
str()
,如str(87)
,結果原來會判別為數字的87變成文字的'87'。 - 轉為整數
int()
。 - 轉為浮點數
float()
。 - 轉為布林
bool()
,非0即為真。
# your code here:
str(87)
儲存容器
-串列 list 、元組 tuple 、集合 Set
串列 list []
計算 | 說明 |
---|---|
x in L | 判斷 x 是否在 L 中 |
x not in L | 判斷 x 是否不在 L 中 |
L + t | 連接 L 及 t |
L * n, n * L | 將 L 重複 n 次連接 L 本身 |
L[i] | 取得索引值 i 的元素 |
L[i:j] | 取得索引值 i 到 j 的子序列 |
L[i:j:k] | 取得索引值 i 到 j ,間隔 k 的子序列 |
len(L) | 回傳 L 的元素個數 |
min(L) | 回傳 L 中的最小值 |
max(L) | 回傳 L 中的最大值 |
L.index(i) | 取得 L 中第一次出現 i 的索引值 |
L.count(i) | 累計 L 中 i 出現的個數 |
L = [9, 5, 2, 7]
L
len(L)
L[0]
L[:] # [魚頭 : 尾前]
L[0:2]
k=['庭','院','深','深','深','幾','許']
#深深深
k[2:5]
!pip install twstock
import twstock
stock = twstock.Stock("2330")
stock.price
stock.price[-1]
計算 | 說明 |
---|---|
L[i] = x | 將索引值 i 的元素指派為 x |
L[i:j] = t | 將索引值 i 到 j 的元素指派為 t , t 為迭代器 |
del L[i:j] | 刪除索引值 i 到 j 的元素 |
L[i:j:k] = t | 將索引值 i 到 j ,間隔 k 的元素指派為 t , t 為迭代器 |
del L[i:j:k] | 刪除索引值 i 到 j ,間隔 k 的元素 |
list comprehension | 列表推導式:運用運算式生成新的串列 |
#for 迴圈
for i in [1,2,3,4]:
print(i*i)
r = []
for i in range(10):
r.append(i)
r
a=[]
for i in range(100):
if i % 2 == 1:
a.append(i)
a
#如以原本寫法如下
L = [9, 5, 2, 7]
result = [] #先創空list
for x in L: #for迴圈逐一判斷
if x > 3: #判斷條件
result.append(x) #符合的結果附加到result串列裡
print(result)
#列表推導式list comprehension
[x for x in L if x > 3]
a = [ i for i in range(10)]
a
b = [ i*i for i in range(10) if i % 2 == 1]
b
%%timeit
a=[ i**2
for i in range(100)
if i % 2 ==1]
a
%%timeit
a=[]
for i in range(100):
if i % 2 == 1:
a.append(i*i)
a
#sorted(iterable, *, key=None, reverse=False)
sorted_L = sorted(L , reverse=True)
sorted_L
計算 | 說明 |
---|---|
list.append(x) | 將 x 附加到 list 的最後 |
list.extend(x) | 將 x 中的元素附加到 list 的最後 |
list.count(x) | 計算 list 中 x 出現的次數 |
list.index(x[, i[, j]]) | 回傳 x 在 list 最小的索引值 |
list.insert(i, x) | 將 x 插入 list 索引值 i 的地方 |
list.pop([i]) | 取出 list 中索引值為 i 的元素,預設是最後一個 |
list.remove(x) | 移除 list 中第一個 x 元素 |
list.reverse() | 倒轉 list 中元素的順序 |
list.sort([key[, reverse]]) | 排序 list 中的元素 |
元組 tuple ()
- 元組 tuple 屬於不可變 (mutable) 的序列 (sequence) 型別,是不可更改的,可進行以下序列通用的計算。
計算 | 說明 |
---|---|
x in s | 判斷 x 是否在 s 中 |
x not in s | 判斷 x 是否不在 s 中 |
s + t | 連接 s 及 t |
s n, n s | 將 s 重複 n 次連接 s 本身 |
s[i] | 取得索引值 i 的元素 |
s[i:j] | 取得索引值 i 到 j 的子序列 |
s[i:j:k] | 取得索引值 i 到 j ,間隔 k 的子序列 |
len(s) | 回傳 s 的元素個數 |
min(s) | 回傳 s 中的最小值 |
max(s) | 回傳 s 中的最大值 |
s.index(i) | 取得 s 中第一次出現 i 的索引值 |
s.count(i) | 累計 s 中 i 出現的個數 |
t = 2, 4, 6, 8
type(t)
L
#更改會報錯
t[0] = 1
2 in t
集合Set {}
- 集合set使用大括弧圍起來,但沒有重複的元素,且無序的存放元素。可將集合視為無鍵的字典物件。
- 針對集合的
in
操作速度非常快,資料量大時更適合。 - 不常用,但用在找出不重複的資料時好用。
s1 = {9,9,5,5,2,2,7,7}
s2 = {9,5,2,7}
s1 == s2
s1
# !pip install jieba
import jieba
text = """2023 iThome 鐵人賽
iThome 鐵人賽是 IT 圈的年度盛事,是推動台灣 IT 技術向上成長的重要力量!每年逾千名 IT 行內人透過鐵人賽「連續 30 天發表技術文章不中斷」,寫出一整年的成長與學習、爆發驚人的技術能量。
鐵人們在賽事中寫下的成果,深獲業界好評與肯定。在博碩文化與 iThome 攜手合作之下,從 2018 年開始,陸續出版了多位得獎者的作品,讓得獎的鐵人們得以分享他們的榮耀與成果,幫助更多的讀者群、發揮更大的影響力,並且在寫code的人生中,為自己寫下最珍貴的那一頁。
在 iThome 鐵人賽的 30 天挑戰中,參賽者每一天都必須努力趕在午夜 12 點前、克服萬難,按下【送出】鍵,更別說賽期中還有中秋、國慶兩大殺手連假。當你已經艱辛奮鬥,攀越學業、社交、職場、家庭等一座座山峰,不管是喘氣休息、還是正駐足欣賞當前美景,是否還有勇氣與毅力,繼續登頂?許多鐵人們回想參賽以來最大的收獲,往往就是「原來我做得到」。
越來越多 IT 人透過 iThome 鐵人賽展現自我,並自豪地將賽事成果列入自己的履歷(讓徵才企業垂涎不已)。不用高估世界,也不用低估自己,今年就和眾多 IT 同儕一起喚醒心中最強大的鐵人!再一步,世界就在你的腳下。"""
wordlist = jieba.cut(text,cut_all=False)
wordlist = [ seg for seg in wordlist ]
wordlist
wordset = set(wordlist)
wordset
'鐵人' in wordlist
%%timeit
'鐵人' in wordlist
%timeit '鐵人' in wordset
計算 | 說明 |
---|---|
x in s | 判斷 x 是否在 s 中 |
x not in s | 判斷 x 是否不在 s 中 |
s1 & s2 | 且運算,取得 s1 與 s2 的交集,等於 s1.intersection(s2) |
s2 | s2 |
s1 ^ s2 | 對稱差運算,取得 s1 與 s2 的對稱差集,等於 s1.symmetric_difference(s2) |
s1 - s2 | 差運算,取得 s1 與 s2 的差集,等於 s1.difference(s2) |
s1 < s2 | 判斷 s1 是否為 s2 的真子集 |
s1 <= s2 | 判斷 s1 是否為 s2 的子集,等於 s1.issubset(s2) |
s1 > s2 | 判斷 s2 是否為 s1 的真子集 |
s1 >= s2 | 判斷 s2 是否為 s1 的子集,等於 s1.issuperset(s2) |
len(s) | 回傳 s 的元素個數 |
min(s) | 回傳 s 中的最小值, s 中的元素必須是相同型態 |
max(s) | 回傳 s 中的最大值, s 中的元素必須是相同型態 |
- 由於 set 型態是可變的,因此有額外兩個新增與刪除元素的方法:
方法 | 說明 |
---|---|
s.add(e) | 增加 e 為 s 的元素 |
s.remove(e) | 從 s 中刪除元素 e |
字典Dictionary
以
{}
以及冒號:
來分隔鍵與值,以創建字典物件建立字典變數可利用大括弧,裡頭以
key:value
為配對的資料項目,每一筆資料再以逗號區隔開,例如d1 = {one:"a", two:"b"}
使用字典須注意, key 必須是不可變的資料型態,且不可重複,如數字、字串 (string) 等; value 沒有限制,因此有需要的話,使用串列 (list) 或字典皆可。
也可以利用字典型態的建構子 (constructor) 建立物件。
- 字典、串列與JSON相似,用法可以相互參照
- 一個公車交通資訊API MOTC Transport API V2
- 一個產品資訊API
```
//
//取得產品列表(Get):/api/livejs/v1/customer/{api_path}/products
{
"status": true,
"products": [
{
"category": "產品分類 (String)",
"image": "產品圖片 (String)",
"id": "產品ID (String)",
"title": "產品名稱 (String)",
"origin_price": "產品原始價錢 (Number)",
"price": "產品銷售價錢 (Number)"
}
]
}
```
{"數學": [100, 90, 80, 70] }
身高體重 = {"andy": [183, 70], "Alice": [163, 45]}
身高體重
{"one":"a", "two":"b"}
- 組成dict的4種方法
dict(one="a", two="b")
dict({"one":"a", "two":"b"})
dict(zip(("one", "two"), ("a", "b")))
dict([["one", "a"], ["two", "b"]])
- 字典物件可進行以下的運算
計算 | 說明 |
---|---|
d[key] | 從 d 中取得 key 的 value |
d[key] = value | 指定 d 的 key 的值為 value |
del d[key] | 刪除 d 的 key 值 |
key in d | 判斷 key 是否在 d 中 |
key not in d | 判斷 key 是否不在 d 中 |
iter(d) | 回傳由 d 的 key 建立的迭代器 |
len(d) | 回傳 d 的配對資料個數 |
- 字典物件的方法 (method)
方法 | 描述 |
---|---|
dict.clear() | 清空 dict 的所有配對資料 |
dict.copy() | 回傳 dict 的拷貝 |
classmethod dict.fromkeys(seq[, value]) | 由 seq 中的元素構成 key ,每個 key 都給相同的 value 值 |
dict.get(key[, default]) | 從 dict 中取得 key 的 value ,若無此 key 則回傳 default , default 預設為 None |
dict.items() | 回傳 dict_items 物件,使 key:value 儲存為序對,然後依序儲存在 dict_items 物件中 |
dict.keys() | 回傳 dict_items 物件,使 key 依序儲存在 dict_items 物件中 |
dict.pop(key[, default]) | 將 key 的 value 從 dict 移除,若無此 kay ,回傳 default |
dict.popitem() | 從 dict 移除任意一組 key:value |
dict.setdefault(key[, default]) | 如果 key 在 dict 中,回傳 value 值,反之,將 key:default 加入 dict 之中 |
dict.update([other]) | 將 dict 以 other 更新 |
dict.values() | 回傳 dict_items 物件,使 value 依序儲存在 dict_items 物件中 |
d1 = {'a' : 'C8763', "b" : [9, 5, 2, 7]}
d1
type(d1["b"])
d1["天線寶寶"]="你好"
d1
bike = [{"地點":"台中火車站","車位":0},{"地點":"高美濕地","車位":100}]
d1['b']
'b' in d1
del d1['b']
d1
d1.keys()
d1.values()
d1.items()
- 可以update方法將字典合併
d1.update({'b':9487 , 'c': 'ithome'})
d1 # 'b':[9,5,2,7]被覆寫掉了
格式化輸出
認識print()函式
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
*objects
: 接受輸出的內容,多筆資料以逗號隔開。sep
: 間隔,預設一個空白。end
: 預設為\n
即換行。file
: 預設為螢幕輸出。flush
: 預設為布清除資料緩衝區。
- 各參數不指定修改即為預設值。
- 未來各種函數詳細內容可參閱文檔,或使用
help(print)
、?print
查詢。
?print
# help(print)
格式化 print() 輸出語法
%
- 以類似C語言的
printf
語法輸出
語法 | 說明 |
---|---|
%s | 輸出文字 |
%f | 輸出浮點數 |
%d | 輸出十進位整數 |
%e、%E | 以科學記號輸出數值 |
%o | 以八進位整數方式輸出數值 |
%x、%X | 以十六進位整數方式輸出數值 |
%c | 以字元方式輸出 |
%r | 以 repr() 函數輸出文字 |
%% | 輸出 % 百分比符號 |
word_1 = 'Main9'
word_2 = '48794'
word_3 = '狂'
print('%s%s%s' % (word_1, word_2, word_3))
#新八戰鬥力
fp = {"新八":362, "一般人":360}
fp["新八"]
print(
"志村新八比一般人強%d個昆布,戰鬥力比一般人高%.2f%%個昆布" %(
fp["新八"] - fp["一般人"],
(fp["新八"] - fp["一般人"])/fp["一般人"] *100)
)
fp1 = fp["新八"] - fp["一般人"]
fp2 = (fp["新八"] - fp["一般人"]) / fp["一般人"] *100
print("志村新八比一般人強%d個昆布,戰鬥力比一般人高%.2f%%個昆布" % (fp1, fp2))
%
空間與對齊
- 控制輸出排版結果,以及控制小數點顯示位數
- 以
%s
的%
及s
中間加入格式語法表示
目的 | 表示 |
---|---|
以m格輸出 | "%ms" % _ |
數值空白前補0 | "%0md" % _ |
以m格靠左對齊 | "%-ms" % _ |
限制輸出字串長度上限 | "%.ms" % _ |
浮點數設定總寬度m及小數位數n | "%m.nf" % _ |
強迫顯示正負號 | "%+d" % _ |
負號顯示、正數留空 | "% d" % _ |
format
format
會自動處理各種類型的資料。- 如有2個以上的格式化輸出內容
# 字串格式化
msg='{}, {}!'.format('Hello','World')
print(msg)
#照順序
print("{} , {}!".format("Hello","World"))
#自編順序
print("{1} , {0}!".format("World","Hello"))
print("志村新八比一般人強{:^+10.3f}個昆布,戰鬥力比一般人高{:.2}%個昆布".format(fp1,fp2))
format
空間與對齊
目的 | 表示 |
---|---|
以m格輸出 | "{:m}".format() |
數值空白前補0 | "{:0m}".format() |
靠右對齊 | "{:>m}".format() |
靠左對齊 | "{:<m}".format() |
置中對齊 | "{:^m}".format() |
限制輸出字串長度上限 | "{:.m}".format() |
浮點數設定總寬度m及小數位數n | "{:m.nf}".format() |
強迫顯示正負號 | "{:+m}".format() |
負號顯示、正數留空 | "{: m}".format() |
f-string
- Python 的格式化輸出自3.6版本起支援以
f
作為字串開頭的格式化代碼,更為簡潔易用。 - 排版比照
format()
用法。
f"{word:m.nf}"
#3種寫法一次比較
name = "巧虎"
age = 3
print("大家好我是%s,我今年%s歲!"% (name, age))
print("大家好我是{},我今年{}歲!".format(name, age))
print(f"大家好我是{name},我今年{age}歲!")
print(f"{name}好乖,叔叔帶你喝養樂多!")
print(f"大家好我是{name:^10},我今年{age:^10.1f}歲!")
import requests
say = "大家好我是啾啾協"
url = f"https://howger.orange.tw/?mode=convert&translate=1&keys={say}&s=1.5"
r = requests.get(url)
mov = r.text.split("id=")[1][:13]
mp4 = f"https://howger.orange.tw/data/{mov}.mp4?"
print(mp4)
from IPython.display import HTML
from base64 import b64encode
HTML(f"""
<video width=800 controls>
<source src={mp4} type="video/mp4">
</video>"""
)
第二個動手做 - 用f-string
製作Google Map 有效的超連結
網址挖洞練習:
- 透過以下程式碼,搜尋地名、經緯度。
- 用地名、經緯度等方法建立有效的 Google Map 連結
- 完成要求:
- 用 f-string
- 輸出連結可連到正確位址
- 換地點
有效連結範例,請好好觀察網址
- 經緯度定位
- 以地標搜尋
- 導航
- https://www.google.com/maps/dir/?api=1&origin=台中火車站&destination=台中高鐵&travelmode=transit (travelmode = [driving, walking, bicycling, transit)
可查閱的資料
!pip install geocoder
# 查經緯度座標,注意Google MAP經緯度少一位數
import geocoder
location_name = "國立台中科技大學" #@param {type:"string"}
location_gps = geocoder.osm(location_name).latlng
print(location_gps)
# 作業- 建立使用 f-string 建立有效的 Google Map 連結
# 完成要求: 1.用 f-string 2.輸出連結可連到正確位址
locate= "???"
url = f'...{locate}.'
print(url)
延伸學習(後續會教)
import requests
# https://www.google.com/maps/search/?api=1&map_action=map&zoom=16&query=24.149660,120.684166
payload = {"api":"1", "map_action":"map", "zoom":"16", "query":"24.149660,120.684166"}
r = requests.get(
'https://www.google.com/maps/search/',
params=payload
)
print(r.url)
params = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=params)
print(r.url)