Python
第四堂
Content
-
Review
-
function
-
recursion
-
decorator
-
lambda
-
class
-
例外處理
-
函式庫
Review
Dictionary
鍵 ( Key ) - 值 ( Value ) 對應,key 需唯一且不可變
d = {'a': 1, 'b': 2}
d1 = {[1, 2]: 1} #TypeError: unhashable type: 'list'
dict methods
d = {'b': 2}
d['a'] = 1
print(len(d)) #2
print(list(d.keys())) #['b', 'a']
print(list(d.values())) #[2, 1]
print(list(d.items())) #[('b', 2), ('a', 1)]
print(d.get('a', "Doesn't exist")) #1
print(d.copy()) #{'b': 2, 'a': 1}
del d['a']
print(d) #{'b': 2}
Format
將輸出內容格式化
a = "Hi, I am %s."
print(a % "pomelo") #Hi, I am pomelo.
b = "I have %d dollars."
print(b % 3.333) #I have 3 dollars.
c = "Now I have %f dollars."
print(c % 3.333) #Now I have 3.333000 dollars.
a = "Hello, I am {}, and I like to eat {}."
print(a.format("pomelo", "apple"))
#Hello, I am pomelo, and I like to eat apple.
b = "Hello, {:-^10s}."
print(b.format("world")) #Hello, --world---.
name = "pomelo"
age = 15.187
print(f"My name is {name}, I am {age} years old.")
#My name is pomelo, I am 15.187 years old.
print(f"Hello {name.upper()}, I am {age:-^.1f} years old.")
#Hello POMELO, I am 15.2 years old.
if - elif - else
條件判斷
a = 1
b = 2
if a > b:
print("a > b")
elif a == b:
print("a == b")
else:
print("a < b")
#a < b
print(a and b) #2
print(a or b) #1
print(0 and b or a) #0
for
for 變數 in 可迭代物件/range():
lst = [1, 3, 4]
for i in lst:
if i > 2:
print(i)
#3 4
for i in range(0, 4, 2):
print(i)
#0 2
while
while 條件:
n = 4
while n > 0:
print(n, end=' ')
n -= 1
#4 3 2 1
function
函式
數學函式
給一個 x 值會對應到某個數值
程式函式
def f(x):
result = x**2 + 2*x + 1
return result
print(f(2)) #9
define,定義函式需要的開頭
函式名稱
要傳入的參數
回傳值
執行函式
Function
函式是一種有名稱且獨立的程式片段,可以接收任何型態的參數,處理完成後也可以輸出任何型態的結果
def 函式名稱(參數1, 參數2...): #定義函式
要執行的程式
return 回傳值
函式名稱(參數1, 參數2...) #執行函式
要先定義函式,才能執行
參數
可以放入多個參數,會按照順序處理
def f(a, b):
return a - b
print(f(1, 2)) #-1 (a = 1, b = 2)
print(f(2, 1)) #1 (a = 2, b = 1)
最多只能輸入與參數數量一樣多的變數值
參數
也可以不放入參數
def f():
return 6
print(f()) #6
關鍵字引數
可以用關鍵字引數設定特定參數內容
def mbi(weight, height):
return weight / (height**2)
print(mbi(height=1.5, weight=45)) #20.0
順序不一樣也沒關係
回傳值
使用 return
回傳值
def f(x):
all = 0
for i in x:
all += i
return all
print(f([1, 2, 4])) #7
回傳值
也可以不回傳值
def f(name):
print(f"Hello, {name}")
a = f("pomero") #Hello, pomero
print(a) #None
會回傳 None
回傳值
遇到 return 時會中止函式並回傳值
def f(x):
all = 0
for i in x:
all += i
if i % 5 == 0:
return all
return all
print(f([1, 3, 5, 6])) #9
print(f([1, 3, 4, 6])) #14
回傳值
def f(x):
all = 0
for i in x:
all += i
if i % 5 == 0:
return all
return all
print(f([1, 3, 5, 6])) #9
print(f([1, 3, 4, 6])) #14
all = 0
all = 1
all = 4
+1
+3
all = 9
+5
return
5 % 5 == 0
回傳值
def f(x):
all = 0
for i in x:
all += i
if i % 5 == 0:
return all
return all
print(f([1, 3, 5, 6])) #9
print(f([1, 3, 4, 6])) #14
all = 0
all = 1
all = 4
+1
+3
all = 8
+4
all = 14
+6
return
end for
回傳值
可以回傳多個結果
def f(x, y, z):
return x+1, y+1, z+1
a = f(1, 2, 3)
print(a) #(2, 3, 4)
會回傳 tuple
回傳值
def f(x, y, z):
return x+1, y+1, z+1
a, b, c = f(1, 2, 3)
print(f"a = {a}, b = {b}, c = {c}")
#a = 2, b = 3, c = 4
會回傳 tuple
可以 unpacking 給多個變數
變數範圍
a = 2
def f(a):
a = 1
print(f"a is {a}")

變數範圍
在函式裡宣告的變數,生命只到函式結束,稱為區域 ( local ) 變數
在函式裡宣告的函式也一樣
def f1():
def f2():
print("Local: f2")
f2()
f1() #Local: f2
f2()
#NameError: name 'f2' is not defined
global
可以把區域變數變成全域 ( global ) 變數
a = 2
def f():
global a
a = 1 #不可寫作:global a = 1
print(f"Global a in func: {a}")
print(f"Before f(), global a = {a}")
f()
print(f"After f(), global a = {a}")
# Before f(), global a = 2
# Global a in func: 1
# After f(), global a = 1
nonlocal
可以修改上層函式中定義的變數
def f1():
a = 2
print(f"Local variable a = {a} in f1")
def f2():
print(f"f2 calls a = {a}")
def f3():
nonlocal a
a = 10
print(f"f3 calls modified a = {a}")
f3()
f2()
print(f"a in f1 = {a}")
f1()
# Local variable a = 2 in f1
# f2 calls a = 2
# f3 calls modified a = 10
# a in f1 = 10
nonlocal
def f1():
a = 2
print(f"Local variable a = {a} in f1")
def f2():
print(f"f2 calls a = {a}")
def f3():
nonlocal a
a = 10
print(f"f3 calls modified a = {a}")
f3()
f2()
print(f"a in f1 = {a}")
f1()
# Local variable a = 2 in f1
# f2 calls a = 2
# f3 calls modified a = 10
# a in f1 = 10
函式若未先在函式被呼叫不會執行
一個函式執行完裡面全部的內容後,才會執行另一個函式
*args
可以傳入多個參數,傳入的參數會被轉為 tuple
def f(*s):
print(s)
f(1, 2, 3, 'a', 'b', 'c')
# (1, 2, 3, 'a', 'b', 'c')
用法:*變數名
**kwargs
可以傳入多個參數,傳入的參數會被轉為 dict
def f(**s):
print(s)
f(name='pomero', age=18, gender='g')
# {'name': 'pomero', 'age': 18, 'gender': 'g'}
用法:**變數名
使用之前要先賦值
* & **
若 *args 和 **kwargs 同時出現,會依照輸入的內容分別套用
def f(*args, **kwargs):
print(f"args: {args}")
print(f"kwargs: {kwargs}")
f([1, 2, 3], 4, x=1, y=2)
# args: ([1, 2, 3], 4)
# kwargs: {'x': 1, 'y': 2}
函式參數
可以把函式當參數
def plus(a, f):
return a + f(a)
def square(a):
return a**2
print(plus(2, square)) #6 (2 + 2**2)
Recursion
遞迴
Recursion
在函式裡呼叫自己或其他函數
def n(a):
if a < 1:
return 1
return a + n(a-1)
Fibonacci
def fib(a):
if a == 1 or a == 2:
return 1
return fib(a-1) + fib(a-2)
print(fib(5)) #5
fib(5)
fib(4) + fib(3)
fib(3) + fib(2)
fib(2) + fib(1)
fib(2) + fib(1)
return 1
return 1
return 1
return 1
return 1
return 2
return 3
return 2
return 5
Factorial
def fact(n):
if n == 0 or n == 1:
return 1
return n * fact(n-1)
print(fact(5)) #120
lambda
匿名函式
lambda
- 不需要定義名稱
- 只能有一行運算式
- 執行完後自動回傳結果
square = lambda x: x**2
print(square(2)) #4
lambda
使用:lambda 參數名稱: 內容
def hi():
print("Hi")
hi() #Hi
p = lambda l: print(l)
p("Hi") #H1
(lambda l: print(l))("Hi") #Hi
第 4 行執行結果跟第 5 ~ 6. 7 行一樣
多個參數
不用使用小括號,需使用逗號分隔參數
POW = lambda x, y: x**y
print(POW(2, 4)) #16
f = lambda *args: print(args)
f(1, 2, 3) #(1, 2, 3)
也可以使用 *args
for
lambda 可以搭配 for 迴圈使用
def x(*args):
lst = []
for i in args:
lst.append(i*2)
return lst
y = lambda *args: [i*2 for i in args]
print(x(1, 2, 3)) #[2, 4, 6]
print(y(1, 2, 3)) #[2, 4, 6]
if
lambda 也可以搭配 if 使用
def x(n):
if n < 10:
return True
else:
return False
y = lambda n: True if n < 10 else False
print(x(11)) #False
print(y(11)) #False
lambda
為什麼不是印出 0, 1, 16 ?
square = []
for i in range(5):
square.append(lambda : i**2)
print(square[0]()) #16
print(square[1]()) #16
print(square[4]()) #16
lambda
為什麼不是印出 0, 1, 16 ?
square = []
for i in range(5):
square.append(lambda : i**2)
print(square[0]) #<function <lambda> at 0x7fcd4a364d30>
print(square[1]) #<function <lambda> at 0x7fcd4a364dc0>
print(square[4]) #<function <lambda> at 0x7fcd4a364f70>
square 裡存的是 lambda
lambda
為什麼不是印出 0, 1, 16 ?
square = []
for i in range(5):
square.append(lambda : i**2)
print(i) #4
print(square[0]()) #16
print(square[1]()) #16
在迴圈結束後執行,i = 4
所以 lambda 裡的 i = 4,會回傳 4**2
lambda
為什麼不是印出 0, 1, 16 ?
square = []
for i in range(5):
square.append(lambda : i**2)
print(square[i]()) #0 1 4 9 16
print(square[0]()) #0 1 4 9 16
如果在迴圈裡執行,會印出正確的結果
lambda
square = []
for i in range(5):
square.append(lambda x=i: x**2)
print(square[0]()) #0
print(square[1]()) #1
print(square[4]()) #16
如果在迴圈裡執行,會印出正確的結果
如果想要在迴圈外執行,可以將參數設為另一個變數
map( )
a = [1, 2, 3, 4, 5, 6]
b = map(lambda i: i+1, a)
print(b) #<map object at 0x7f7a81b87130>
print(list(b)) #[2, 3, 4, 5, 6, 7]
map( function, iterable object )
map 會根據特定函式對指定的序列做映射
意思就是依據函式去改變後面序列的內容
filter( )
a = [1, 2, 3, 4, 5, 6]
b = filter(lambda i: i>3, a)
print(list(b)) #[4, 5, 6]
filter( function, iterable object )
filter 會根據特定函式對指定的序列做過濾
意思就是依據函式去過濾後面序列的內容,將回傳為 True 的項目留下
decorator
裝飾器
decorator
- 讓程式碼達到精簡又漂亮的寫法
- 讓其他函式或類別,在不需要做任何程式碼修改的前提下增加額外功能
- 裝飾器的返回值是一個函式或類別
decorator
def a(func):
print("a")
return func
def b():
print("b")
c = a(b) #a
print(c) #<function b at 0x7f7eebe74dc0>
c() #b
函數可以當作參數傳遞並執行
語法糖 @
def a(func):
print("a")
return func
#裝飾 b
@a
def b():
print("b")
b()
#a
#b
用語法糖包裝來簡化
多個裝飾器
def a1(func):
print(1)
return func
def a2(func):
print(2)
return func
def a3(func):
print(3)
return func
@a1
@a2
@a3
def b():
print("go!!!")
b()
用語法糖包裝來簡化

class
類別
class
可以建立一個自訂的型態
class class_name():
a = 123
def f():
...
class_name.a
class_name.f()
__init__
依附於類別的變數,用 __init__ 來定義
class person():
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
id = 1 #也可以這樣設定
a = person("poemro", "F", 18)
print(a.name, a.gender, a.age)
#poemro F 18
__init__
也可以用關鍵字參數
class person():
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age
id = 1
a = person(name="pomero", age=18, gender="F")
print(a.name, a.gender, a.age)
#poemro F 18
函式
可以在 class 定義函式
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
id = 1
def eat(self):
self.money -= 100
self.weight += 5
p = person("Hey", 1000, 50)
p.eat()
print(p.money, p.weight) #900 55
函式
可以用物件改物件
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
class rest():
def food(self, guest):
guest.money -= 100
guest.weight += 5
p = person("Hey", 1000, 50)
r = rest()
r.food(p)
print(p.money, p.weight) #900 55
覆寫屬性
如果從外部定義了和類別屬性名稱相同的屬性,就會被覆寫
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
def say(self, text):
print(f"Hi, {text}")
p = person("Hey", 1000, 50)
p.say("hey") #Hi, hey
p.say = "???"
print(p.say) #???
getter & setter
用 getter 去讀取私有成員
用 setter 去修改私有成員
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
def get_salary(self):
return self.__salary
def set_salary(self, new_salary):
self.__salary = new_salary
__salary = 30000
p = person("Hey", 1000, 50)
print(p.get_salary()) #30000
p.set_salary(28000)
print(p.get_salary()) #28000
繼承
繼承 ( inheritance ) 可以延續利用父類別的特性並加以修改
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
class student(person): #student 繼承 person
id = 1 #新增 id
def eat(self, m):
self.money -= m
self.weight += m #可以使用 person 的屬性
s = student("Hey", 1000, 50)
print(s.id) #1
s.eat(10)
print(s.money, s.weight) #990 60
super( )
可以繼承父類別的方法
class person():
def __init__(self, name, money, weight):
self.name = name
self.money = money
self.weight = weight
class student(person):
def __init__(self, name, money, weight, id):
super().__init__(name, money, weight)
#繼承 parent 的 __init__
self.id = id
s = student("Hey", 1000, 50, 1)
print(s.name, s.id) #Hey 1
多重繼承
class meat():
def __init__(self, source, doneness, kg):
self.source = source
self.doneness = doneness
self.kg = kg
def cook(self, time):
if time < self.doneness:
print("Time is too short.")
class bread():
def __init__(self, kind):
self.kind = kind
class burger(meat, bread): #繼承 meat 跟 bread
def __init__(self, source, doneness, kg, kind):
meat.__init__(self, source, doneness, kg)
bread.__init__(self, kind)
b = burger("USA", 7, 10, "rye")
b.cook(6) #Time is too short.
例外處理
try & except
例外處理
When an error occurs, or exception as we call it, Python will normally stop and generate an error message.
These exceptions can be handled using the
try
statement.
try & except
try: #如果 print(x) 可以執行
print(x)
except: #如果 print(x) 會有錯誤
print("Something wrong")
#Something wrong
print(x) #NameError: name 'x' is not defined
如果直接執行 print(x)
使用例外處理,讓程式能繼續運行
except
except 的錯誤訊息
錯誤訊息 | 說明 |
---|---|
NameError | 使用沒有被定義的對象 |
IndexError | 索引值超過了序列的大小 |
TypeError | 數據類型 ( type ) 錯誤 |
SyntaxError | 語法規則錯誤 |
ValueError | 傳入值錯誤 |
KeyboardInterrupt | 當程式被手動強制中止 |
AssertionError | 程式 asset 後面的條件不成立 |
KeyError | 鍵發生錯誤 |
ZeroDivisionError | 除以 0 |
AttributeError | 使用不存在的屬性 |
IndentationError | 語法錯誤 ( 沒有對齊 ) |
IOError | Input/output異常 |
UnboundLocalError | 區域變數和全域變數發生重複或錯誤 |
except
try:
print(a)
except IndexError:
print("IndexError")
except NameError:
print("NameError")
#NameError
在 except 後放錯誤型別
try:
print(a)
except IndexError:
print("IndexError")
except Exception as e:
print(e)
#name 'a' is not defined
except Exception as 變數
可以印出全部的錯誤訊息
pass
try:
print(a)
except:
pass
print("hello")
#hello
使用 pass 略過
else
a = input("Input: ")
try:
a = int(a)
print(a)
except:
print("Error")
else:
print("No error")
如果沒有錯誤,會執行 else


finally
a = input("Input: ")
try:
a = int(a)
print(a)
except:
print("Error")
else:
print("No error")
finally:
print("Always print this")
不管有沒有錯誤,都會執行 finally


raise
a = input("Input: ")
print(a)
if not type(a) is int:
raise TypeError("Only interger are allowed.")
print(f"{a} is int")
可以用 raise 強制中斷程式或拋出錯誤訊息

assert
try:
a = int(input('Input 0~9:'))
assert a <= 9, f"{a} is not in range"
print(a)
except AssertionError as msg:
print(msg)
except:
print('sth wrong')
print('Continue')
assert 條件, 訊息
當條件為 False 時會執行


模組
modules
模組
包含 Python 程式碼的檔案,可以引入
import math #引入叫 math 的模組
print(math.floor(123.2)) #使用 math 裡的函式 floor
import
import 模組名稱
import datetime
print(datetime.date.today()) #2024-10-27
from
from 模組名稱 import 方法
from datetime import date
print(date.today()) #2024-10-27
只匯入模組中的某一段程式
as
import 模組名稱 as 別名
import datetime as dd
print(dd.date.today()) #2024-10-27
將模組賦予別名
import python file
可以 import 自己寫的 .py 檔案
.
└── module
├── main.py
└── module.py
#module.py
def square(a, b):
return a ** b
s = "String from hello"
class stu():
def __init__(self, name, age):
self.name = name
self.age = age
def infor(self):
return f"My name is {self.name}, I'm {self.age} years old."
#main.py
from module import square, s, stu
print(square(2, 4))
print(s)
stu1 = stu("pomero", 16)
print(stu1.infor())

印出來的結果:
結束啦 :D
Python - 4
By pomer0
Python - 4
- 125