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) #0for
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 2while
while 條件:
n = 4
while n > 0:
print(n, end=' ')
n -= 1
#4 3 2 1function
函式
數學函式
給一個 x 值會對應到某個數值
程式函式
def f(x):
result = x**2 + 2*x + 1
return result
print(f(2)) #9define,定義函式需要的開頭
函式名稱
要傳入的參數
回傳值
執行函式
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])) #14all = 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])) #14all = 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 definedglobal
可以把區域變數變成全域 ( 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 = 1nonlocal
可以修改上層函式中定義的變數
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 = 10nonlocal
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)) #5fib(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)) #120lambda
匿名函式
lambda
- 不需要定義名稱
- 只能有一行運算式
- 執行完後自動回傳結果
square = lambda x: x**2
print(square(2)) #4lambda
使用: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)) #16f = 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)) #Falselambda
為什麼不是印出 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]()) #16lambda
為什麼不是印出 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 60super( )
可以繼承父類別的方法
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
trystatement.
try & except
try: #如果 print(x) 可以執行
print(x)
except: #如果 print(x) 會有錯誤
print("Something wrong")
#Something wrongprint(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 definedexcept 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 裡的函式 floorimport
import 模組名稱
import datetime
print(datetime.date.today()) #2024-10-27from
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
- 182