Function & Class
Python - Lesson 4
講師:溫室蔡
什麼是函式
什麼是函式
f (x) = 2x + 3
f (3) = 9
f (7) = 17
Python 中的函式
def f(x):
return 2*x + 3
print(f(3)) # 9
print(f(7)) # 17
函式語法
def 函數名稱(參數1, 參數2, ...):
# 你要做的事情
# ...
# ...
return 回傳值
P.S. "def" 是 "define"(定義)的意思
函式不一定要回傳值
def greet(name):
s = 'Hello, ' + name + '!'
print(s)
greet('John') # Hello, John!
greet('Mike') # Hello, Mike!
變數作用範圍
def greet(name):
s = 'Hello, ' + name + '!'
print(s)
greet('John') # Hello, John!
greet('Mike') # Hello, Mike!
print(s) # NameError: name 's' is not defined
在函式內定義的變數
只作用於函式範圍內
遞迴(recursion)
def fact(n):
if n == 1:
return 1
return n * fact(n-1)
在函式當中呼叫自己
遞迴範例:階乘
def fact(n):
if n == 1:
return 1
return n * fact(n-1)
1! = 1
n! = n (n – 1)!
4! = 4×3×2×1
= 4×3!
遞迴範例:費氏數列
a1 = 1
a2 = 1
an = an–1 + an–2
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
遞迴範例:費氏數列
a1 = 1
a2 = 1
an = an–1 + an–2
def fib(n):
if n == 1 or n == 2:
return 1
return fib(n-1) + fib(n-2)
Python 函式小技巧
回傳多個值
def max_min(n):
a = max(n)
b = min(n)
return a, b
n = [8, 4, 3, 7, 1]
x, y = max_min(n)
print(x) # 8
print(y) # 1
參數預設值
def greet(name, time='morning'):
print(f'Good {time}, {name}!')
greet('John') # Good morning, John!
greet('John', 'evening')
# Good evening, John!
greet('John', 'night')
# Good night, John!
不定數目參數
def double(*a):
for i in a:
print(i*2)
double(3) # 6
double(2, 3, 4)
# 4
# 6
# 8
把函式當參數
def vfunc(a, f):
n = []
for i in a:
n.append(f(i))
return n
def plus_one(x):
return x+1
def square(x):
return x*x
x = [1, 2, 3]
print(vfunc(x, plus_one)) # [2, 3, 4]
print(vfunc(x, square)) # [1, 4, 9]
Class(類別)
定義一個物件(object)
每個物件會有自己的變數
稱為屬性(attribute)
以及自己的函式
稱為方法(method)
例:人有名字(屬性,字串)
體重(屬性,數字)
會吃東西(方法)
寫一個 Class
class Person:
def __init__(self, name, height, weight, money):
self.name = name
self.height = height
self.weight = weight
self.bmi = weight / (height/100)**2
self.money = money
p = Person('Justin', 170, 60, 1000)
print(p.name) # Justin
print(p.height) # 170
print(p.weight) # 60
print(p.bmi) # 20.76
print(p.money) # 1000
Class 語法
class 類別名稱:
def __init__(self, 參數1, 參數2, ...):
self.屬性1 = 值1
self.屬性2 = 值2
# ...
# 其他一開始要做的事
變數 = 類別名稱(參數1, 參數2, ...)
__init__() 是 initialization 的意思
也就是「初始化」
在物件被建立的時候
先做一些設定之類的事
Class 範例:Food
class Food:
def __init__(self, name, price, kcal):
self.name = name
self.price = price
self.kcal = kcal
foods = []
foods.append(Food('apple', 50, 70))
foods.append(Food('banana', 30, 100))
foods.append(Food('orange', 40, 50))
print(foods[0].name) # apple
print(foods[1].price) # 30
print(foods[2].kcal) # 50
寫一個方法
class Person:
def __init__(self, name, height, weight, money):
self.name = name
# 以下略
def eat(self, food):
if self.money < food.price:
print('Too expensive')
return
self.money -= food.price
self.weight += food.kcal / 100
print(f'{name} ate a {food.name}!')
p = Person('Justin', 170, 60, 1000)
f = Food('apple', 50, 70)
p.eat(f) # Justin ate a apple!
print(p.money) # 950
print(p.weight) # 60.7
寫一個方法
class Person:
# ...
# ...
p.eat(f)
print(p.weight) # 60.7 (增加了)
print(p.bmi) # 20.7 (沒跟著改)
self.bmi 與 self.weight 連動
self.eat() 改了 self.weight
但沒改到 self.bmi
成員權限
其中 private 成員只能被自己內部存取
前面加兩條下劃線可讓成員變成 private
class Example:
def __init__(self):
self.x = 10 # public
self.__y = 20 # private
a = Example()
print(a.x) # 10
print(a.y) # AttributeError
print(a.__y) # AttributeError
class 的成員分成 public 跟 private
成員權限
class Example:
def __init__(self):
self.x = 10 # public
self.__y = 20 # private
def y(): # Getter
return self.__y
def set_y(value): # Setter
self.__y = value
a = Example()
print(a.y()) # 20
a.set_y(37)
print(a.y()) # 37
如果要存取 private 成員
就要寫 getter 跟 setter
分別用來取值與賦值
成員權限
class Person:
def __init__(self, name, height, weight, money):
# ...
self.__weight = weight
# ...
def weight(): # Getter
return self.__weight
def set_weight(weight): # Setter
self.__weight = weight
self.bmi = weight / (self.height/100)**2
def eat(self, food):
# ...
self.set_weight(self.weight() + food.kcal / 100)
# ...
# ...
p.eat(f) # Justin ate a apple!
print(p.weight) # AttributeError: type object 'Person' has no attribute 'weight'
print(p.__weight) # AttributeError: type object 'Person' has no attribute '__weight'
print(p.weight()) # 60.7
print(p.bmi) # 21.0
繼承(inheritance)
若 B 繼承了 A
則 B 會有 A 的
所有屬性與方法
同時還能
再為 B 定義
專屬的成員
class A:
def __init__(self, x, y):
self.x = x
self.y = y
def do_a(self):
print('I can do A')
class B(A):
def __init__(self, x, y, z):
super().__init__(x, y)
self.z = z
def do_b(self):
print('It is possible for me to do B')
p = A(1, 2)
q = B(3, 4, 5)
print(p.x) # 1
print(q.x) # 3
print(q.z) # 5
p.do_a() # I can do A
q.do_a() # I can do A
q.do_b() # It is possible for me to do B
繼承語法
class 類別名稱B(被繼承的類別A):
def __init__(self, A的參數, B自己的參數):
super().__init__(A的參數) # 跑一遍 A 的 __init__()
self.B自己的參數1 = 值1 # 自己的參數自己 init
self.B自己的參數2 = 值2
# ...
# 自己的方法自己寫
def B自己的方法1(self, 參數1, 參數2, ...):
# ...
def B自己的方法2(self, 參數1, 參數2, ...):
# ...
#...
繼承範例:Student
class Person:
# ...
class Student(Person):
def __init__(self, name, height, weight, money, iq):
super().__init__(name, height, weight, money)
self.iq = iq
self.grades = {}
def study(self, hours):
self.iq += hours / 10
def take_test(self, subject, luck):
score = int(iq/150 * 100 * luck)
self.grades[subject] = score
if (score > 80):
money += 100
s = Student('Justin', 170, 60, 300, 120)
s.eat(Food('apple', 50, 70)) # Justin ate a apple!
s.study(2)
print(s.iq) # 120.2
s.take_test('math', 0.9)
print(s.grades['math']) # 72
謝幕
講到這邊也夠了
如果想學更多物件導向的話
歡迎來上星期三的專案建置小社