這篇文章是閱讀Asabeneh的30 Days Of Python: Day 17 - Exception Handling後的學習筆記與心得。
是的,原文章是在Day 17提到,但這怎麼看都不像例外處理,因此我想拿到Day 18討論。
基本上就像是JavaScript中的展開運算子(spread syntax)的用法:
*
**
假設我們有個函式get_date_object
接收三個參數day
, month_name
,和year
:
from datetime import datetime
def get_date_object(day, month_name, year):
date_string = "%s %s, %s" %(day, month_name, year)
return datetime.strptime(date_string, "%d %B, %Y")
date_param = ["24", "December", "2022"]
# results TypeError
date_object = get_date_object(date_param)
print(date_object)
date_param
是一個list,不能直接當參數傳入get_date_object
否則會產生TypeError
。*
像:get_date_object(*date_param)
,就能順利拿到並印出2022-12-24 00:00:00
就像在 Day 5 List 時提到的開箱用法:
numbers = [1, 2, 3, 4, 5, 6, 7]
one, *middle, last = numbers
print(one, middle, last) # 1 [2, 3, 4, 5, 6] 7
如果是字典(dictionary),則加的是**
from datetime import datetime
def get_date_object(day, month_name, year):
date_string = "%s %s, %s" %(day, month_name, year)
return datetime.strptime(date_string, "%d %B, %Y")
date_param = {"day": "24", "month_name": "December", "year": "2022"}
date_object = get_date_object(**date_param)
print(date_object)
*
會產生錯誤:"ValueError: time data 'day month_name, year' does not match format '%d %B, %Y'",看起來是變成拿到key
而非value
。這裡針對 list 的打包用法在Day 11 Functions有提到過,效果就像JS中的其餘參數(rest parameter):
def sum_all(*args):
s = 0
for i in args:
s += i
return s
print(sum_all(1, 2 ,3))
如果是打包 dictionary 的話也跟上面開箱一樣,改用**
就行了:
def packing_person_info(**kwargs):
for key in kwargs:
print(f"{key} = {kwargs[key]}")
return kwargs
print(packing_person_info(name="John", city="Taipei", age=25))
印出的結果如下:
name = John
city = Taipei
age = 25
{'name': 'John', 'city': 'Taipei', 'age': 25}
同樣開箱的用法,也可以用在展開上,就像JS的...
那樣:
# for list
lst_one = [1, 2, 3]
lst_two = [4, 5, 6, 7]
lst = [0, *lst_one, *lst_two]
print(lst) # [0, 1, 2, 3, 4, 5, 6, 7]
# for dictionary
test = {"foo": "bar", "beep": "boop", "hello": "tmp"}
result = {**test, "hello": "world"}
print(result) # {'foo': 'bar', 'beep': 'boop', 'hello': 'world'}
如果想要像JS中的map((item, index) => unknown)
一樣拿到index
參數的話,可以用enumerate
:
enumerate(iterable, start=0)
colors = ["red", "blue", "green", "yellow", "orange"]
for index, color in enumerate(colors):
print (index, color)
上面這個例子會輸出:
0 red
1 blue
2 green
3 yellow
4 orange
也可以用list()
和tuple()
轉換enumerate object:
colors = ["red", "blue", "green", "yellow", "orange"]
print(list(enumerate(colors)))
# [(0, 'red'), (1, 'blue'), (2, 'green'), (3, 'yellow'), (4, 'orange')]
print(tuple(enumerate(colors)))
# ((0, 'red'), (1, 'blue'), (2, 'green'), (3, 'yellow'), (4, 'orange'))
若需要結合兩個 list 的操作,可以使用zip
函式:
zip(*iterables, strict=False)
strict
這個參數若為True會檢查iterables
的資料長度是否都相同,否則會產生ValueError。colors = ["red", "blue", "green", "yellow", "orange"]
hex_code = ["#FF0000", "#0000FF", "#00FF00" , "#FFFF00", "#FFA500"]
color_code = [{"color": color, "hex": code} for color, code in zip(colors, hex_code)]
print(color_code)
# [{'color': 'red', 'hex': '#FF0000'}, {'color': 'blue', 'hex': '#0000FF'}, {'color': 'green', 'hex': '#00FF00'}, {'color': 'yellow', 'hex': '#FFFF00'}, {'color': 'orange', 'hex': '#FFA500'}]
strict
參數看的是傳入的iterables
的資料長度是否不同:
False
(預設)的情況下,會以最短的那個遍歷完就終止並回傳,跟Python的 map
函式一樣。True
的情況下,會產生ValueError:origin_color = ["red", "green", "blue"]
hex_code = ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FFA500"]
print(tuple(zip(origin_color, hex_code, strict=False)))
# (('red', '#FF0000'), ('green', '#00FF00'), ('blue', '#0000FF'))
print(tuple(zip(origin_color, hex_code, strict=True)))
# ValueError: zip() argument 2 is longer than argument 1