Skip to main content

PythonBasic_2

Open In Colab

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

  • 經條件判斷後,回傳結果為TrueFalse
  • 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換行
\ttab

檢查資料型態

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)
s2s2
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) 建立物件。

  • 一個產品資訊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 連結
  • 完成要求:
    1. 用 f-string
    2. 輸出連結可連到正確位址
    3. 換地點

有效連結範例,請好好觀察網址

可查閱的資料

!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)