基礎 Python
李智揚
1
函式
function
2
function 函式(函數)
● 將重複使用的程式碼包裝在函式中使用
● 函式有名稱、包含獨立的程式片段
● 可以接收任意數量和型態的輸入參數(parameters)
● 可回傳(return)任何數量與型態的輸出結果
定義函式 函式名稱 輸入參數
(definition)
def myFunction(參數0, 參數1, …):
…
return 結果
3
呼叫函式
def greeting():
print('Hello~')
return
greeting() # 使用小括號呼叫函式
# Hello~
4
利用回傳值
def agree():
return True
if agree():
print('I Agree!')
else:
print('I Disagree')
# I Agree!
5
練習題
寫一個函數 calculate_sum(),該函數會計算並返回從 1 到
10 的整數總和。
HINT: 55
6
函式引數(arguments)與參數(parameters)
def echo(string):
return f'{string} ~~~~~ {string}'
echo_str = echo('LaLaLa')
print(echo_str)
# LaLaLa ~~~~~ LaLaLa
1. 使用echo函式,並將字串作為引數(arguments)傳入函式
2. 在函式中,以string參數代表外部傳入引數
3. 使用string參數進行運算,並返回運算成果
7
函式回傳值
def add_and_multiply(a, b):
return a+b, a*b
values = add_and_multiply(3, 2)
print(values) # (5, 6)
add, multiply = values
print(add, multiply) # 5 6
add, multiply = add_and_multiply(3, 2)
print(add, multiply) # 5 6
8
試試看
撰寫函式,接受矩形的長和寬作為參數,並同時回傳面積和周長
a, b = rectangle(1, 2)
a # 2
b # 6
9
None
通常inplace函式不會return (None)
● 空值、缺失值、沒有有效值或未知值 my_list.sort()
● type: NoneType my_list.append()
● 作為預設函式返回 值 …
● 初始化變數時未知初始 值
def empty_function(): my_variable = None
return # ...
my_variable = 56
result = empty_function()
print(result) # None
10
None: 檢查None
thing = None
if thing:
print("Something")
else:
print("No thing")
# No thing
thing = None
if thing is None:
print("Nothing")
else:
print("Something")
# Nothing
11
試試看
def whatisit(thing):
if thing is None:
print(f'{thing} is None')
elif thing:
print(f'{thing} is True')
else:
print(f'{thing} is False')
# 使用以上函式測試以下的值
None, True, False,
0, 0.0, '', (), [], {}, set(),
0.01, [0], [''], ' '
12
位置引數 positinal argument
def menu(starter, main, dessert):
return {
'starter': starter,
'main': main,
'dessert': dessert
}
print(menu('salad', 'steak', 'icecream'))
# {'starter': 'salad', 'main': 'steak', 'dessert': 'icecream'}
print(menu('icecream', 'steak', 'salad'))
# {'starter': 'icecream', 'main': 'steak', 'dessert': 'salad'}
13
關鍵字引數 keyword argument
def menu(starter, main, dessert):
return {
'前菜': starter,
'主菜': main,
'甜點': dessert
}
print(menu(main='steak', dessert='icecream', starter='salad'))
# {'前菜': 'salad', '主菜': 'steak', '甜點': 'icecream'}
# 混用位置+關鍵字引數
print(menu('salad', dessert='icecream', main='steak'))
14
預設參數值
def menu(starter, main, dessert='pudding'):
return {'前菜': starter, '主菜': main, '甜點': dessert}
print(menu('salad', 'steak'))
# {'前菜': 'salad', '主菜': 'steak', '甜點': 'pudding'}
print(menu('salad', 'steak', 'tiramisu'))
# {'前菜': 'salad', '主菜': 'steak', '甜點': 'tiramisu'}
15
試試看
題目:生成一個帶有問候語的字串
輸入:姓名
輸入:問候語,預設值: Hey
輸入:結尾符號,預設值: !
輸出:字串
result = generate_greeting("Bob", "Hi")
print(result) # 輸出: Hi, Bob!
result = generate_greeting("Charlie", "Greetings", "?")
print(result) # 輸出: Greetings, Charlie?
result = generate_greeting("Apple")
print(result) # 輸出: Hey, Apple!
16
* :解開束縛,收集位置引數
def print_args(*args):
print("Positional args tuple: ", args)
def print_args(*params):
print("Positional args tuple: ", params)
print_args()
# Positional args tuple: ()
print_args('a')
# Positional args tuple: ('a',)
print_args('a', 'b', 'c')
# Positional args tuple: ('a', 'b', 'c')
17
*args: 接受動態數量引數
def use_dynamic_args(require0, require1, *args):
print('Require0: ', require0)
print('Require1: ', require1)
print('Others: ', args)
use_dynamic_args('Hi', 'Hey', 'Hello', 'Yo bro')
# Require0: Hi
# Require1: Hey
# Others: ('Hello', 'Yo bro')
18
*args 解開包裝進階用法
def use_dynamic_args(require0, require1, *args):
print('Require0: ', require0)
print('Require1: ', require1)
print('Others: ', args)
use_dynamic_args('a', 'b', 'c')
# Require0: a
# Require1: b
# Others: ('c',)
args = (3, 4)
use_dynamic_args(1, 2, args) # use_dynamic_args(1, 2, (3, 4))
# Require0: 1
# Require1: 2
# Others: ((3, 4),)
use_dynamic_args(1, 2, *args) # use_dynamic_args(1, 2, 3, 4)
# Require0: 1
# Require1: 2
# Others: (3, 4)
19
**kwargs 解開束縛,收集關鍵字引數
def print_kwargs(**kwargs):
print(f'print_kwargs: {kwargs}')
print_kwargs()
# print_kwargs: {}
print_kwargs(main='steak', dessert='icecream', starter='salad')
# print_kwargs: {'main': 'steak', 'dessert': 'icecream', 'starter': 'salad'}
20
引數順序
def print_menu(drink, *args, **kwargs):
print(f'單點: {drink}')
for arg in args:
print(f'加點: {arg}')
for key, value in kwargs.items():
print(f'{key}: {value}')
print_menu('珍珠奶茶', '椰果', '芋圓', ice='少冰', sugar='微糖')
# 單點: 珍珠奶茶
# 加點: 椰果
# 加點: 芋圓
# ice: 少冰
# sugar: 微糖
21
試試看
寫一個函式 dynamic_adder,它可以接受不定數量的參數,並回傳它們的總和。
result = dynamic_adder(1)
print(result) # 1
result = dynamic_adder(1, 2)
print(result) # 3
result = dynamic_adder(1, 2, 3)
print(result) # 6
22
內部函式:函式 in 函式
def outer_func(a, b):
def inner(c, d):
return c + d
return inner(a, b)
outer_func(2, 3) # 5
def add_two_even(a, b):
def make_even(x):
return x // 2 * 2
return make_even(a) + make_even(b)
add_two_even(2, 3) # 4
23
__name__, __doc__
def myFunc():
'''我的函式 自己做主'''
print('The name of this function: ', myFunc.__name__)
print('The docstring is: ', myFunc.__doc__)
myFunc()
# The name of this function: myFunc
# The docstring is: 我的函式 自己做主
24
lambda: 匿名函式
lambda arguments: expression
numbers = [1, 2, 3, 4]
def add_100_to_numbers(numbers, func):
for n in numbers:
print(func(n))
def add_100(a):
return a+100
add_100_to_numbers(numbers, add_100)
add_100_to_numbers(numbers, lambda n: n+100)
# 101
# 102
# 103 ● 將lambda函式當作輸入引數
# 104
● 此lambda函式接收一個輸入引數
● 輸出: 引數+100
25
lambda: 匿名函式
lambda x, y: x + y
# v.s
def add(x, y):
return x+y
is_even = lambda x: x % 2 == 0
print(is_even(7)) # 輸出: False
(lambda x: x % 2 == 0)(7) # 輸出: False
names = ['Alice', 'Bob', 'Charlie', 'David']
names.sort(key=lambda x: len(x))
print(names) # 輸出: ['Bob', 'Alice', 'David', 'Charlie']
26
名稱空間(namespace) 與 作用域(scope)
name = 'Eric'
def print_global():
print('inside global: ', name)
print('at top level: ', name)
# at top level: Eric
print_global()
# inside global: Eric
27
名稱空間(namespace) 與 作用域(scope)
name = 'Eric'
def change_name():
print('inside global: ', name)
name = 'Messi'
print('change name: ', name)
change_name()
# UnboundLocalError: local variable 'name' referenced before assignment
28
作用域(scope)
name = 'Eric'
def change_name():
name = 'Messi'
print('change name: ', name)
change_name()
# change name: Messi
print('at top level: ', name)
# at top level: Eric
29
作用域(scope): global
name = 'Eric'
def change_name():
global name
name = 'Messi'
print('change name: ', name)
change_name()
# change name: Messi Clarity is better than obscurity
print('at top level: ', name)
明確勝於晦暗
# at top level: Messi
30
遞迴 (recursion)
def fibonacci(n):
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n+1):
a, b = b, a + b
return b
for i in range(6):
print(fibonacci(i))
# 0, 1, 1, 2, 3, 5
31
遞迴 (recursion)
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
for i in range(6):
print(fibonacci(i))
# 0, 1, 1, 2, 3, 5
To iterate is human, to recursive, divine!
遞迴只應天上有,凡人應當用迴圈
L Peter Deutsch
32
例外處理
myList = [1, 2, 3, 4]
index = 5566
myList[index]
# IndexError: list index out of range
33
例外處理:try / except
myList = [1, 2, 3, 4]
index = 5566
try:
myList[index]
except:
print(f'爆炸啦! 0 < index < {len(myList)}')
# 爆炸啦! 0 < index < 4
34
例外處理:try / except
myList = [1, 2, 3, 4]
while True:
value = input("輸入位置: [q 結束]: ")
if value == 'q':
break
try:
index = int(value)
print(myList[index])
except IndexError as error:
print('Wrong index: ', index)
except Exception as other_error:
print('Something is wrong: ', other_error)
finally:
print('Finally') # 無論如何都會執行
# 輸入位置: [q 結束]: 4
# Wrong index: 4
# Finally
# 輸入位置: [q 結束]: sdaf
# Something is wrong: invalid literal for int() with base 10: 'sdaf'
# Finally 35
進階函式
36
函式: 一級公民 def favorite():
print('Messi')
● 可當作變數
● 可當作引數 favorite() # Messi
● 可當作返回值
● 可儲存在資料結構中 # 傳入favorite本身
# 不是favorite()執行完的結果
# 在say中執行輸入的引數,引數是個函式
def say(func):
func()
say(favorite) # Messi
type(say) # function
type(favorite) # function
37
透過傳入的函式改變行為
def do_something(func, args0, args1):
print(func(args0, args1))
def add(a, b):
return a+b
def to_string(a,b):
return str(a) + str(b)
do_something(add, 3, 6) # 9
do_something(to_string, 3, 6) # 36
38
生成器 generator:動態生成值
● 製作序列的物件
● 可用來迭代大型序列,使用較少量記憶體
● 可記憶狀態
● e.g: range(start, stop, step)
def my_range(first=0, last=5, step=1): for i in my_range():
number = first print(i)
while number < last: # 0
yield number # 1
number += step # 2
# 3
# 4
39
裝飾器 decorator:為函式加上額外功能
# 定義一個簡單的裝飾器
def my_decorator(func):
def wrapper():
print("Before function call")
func()
print("After function call")
return wrapper
# 使用裝飾器
@my_decorator
def say_hello():
print("Hey Apple!")
# 呼叫被裝飾後的函數
say_hello()
40
裝飾器 decorator:為函式加上額外功能
# 定義一個簡單的裝飾器
def say_first(func):
def wrapper():
print(f"要用 {func.__name__} 要早說")
func()
print("晚了就不要了")
return wrapper
# 使用裝飾器
@say_first
def say_hello():
print("Hey Apple!")
# 呼叫被裝飾後的函數
say_hello()
# 要用 say_hello 要早說
# Hey Apple!
41
# 晚了就不要了
裝飾器 decorator:為函式加上額外功能
def document_func(func):
def new_func(*args, **kwargs):
print('執行函式:', func.__name__)
print('位置引數', args)
print('關鍵字引數', kwargs)
result = func(*args, **kwargs)
print('Result: ', result)
return result
return new_func
@document_func
def add_two(a, b): 執行函式: add_two
return a+b
位置引數 (100, 23)
add_two(100, 23) 關鍵字引數 {}
Result: 123
123
42
試試看
定義一個名叫testMicrophone的裝飾器,用它在一個函式被呼叫時印出"test 1, 2, 3
麥克風測試 ",函式結束時印出"麥克風測試完畢 "
被裝飾的函式自訂,或用以下函式
def myFunc():
print("太神啦~~~")
43
試試看
撰寫一個例外處理:當捕捉到除法的除數為0時,印出"分母不可為0"
Hint: 可以先弄爆你的除法,取得該錯誤的種類
44
Python 常用內建函式
45
Python 內建函式
Build-in functions
46
eval, exec: 執行動態程式碼
# 執行程式碼
result = eval('1+2+3')
print(result) # 6
# 將字串中的變數當成程式碼執行
x = 1
result = eval('x+1')
print(result) # 2
# 執行函式/使用類別
eval('print("hello")') # hello
# 轉換成數字
age = input("age: ")
a = eval(age)
print(a, type(a))
47
eval, exec: 執行動態程式碼
code_str = """
x = 15
y = 20
print(x + y)
"""
exec(code_str) # 35
使用動態執行方法時,要小心!
48