Python Comprehension: 迴圈與 lambda 的結合
Comprehension 可簡單的想成是 迴圈與 lambda 的結合,
也可想成是 Java 中的 streaming。
基本上便是將一個集合的資料依序執行指定的動作,
然後再回傳一個有序或無序的資料集。
- Python 中其他相似功能
- filter function
- map function
- zip function
- reduce function
Comprehension 語法
result = [ expression for x in collection if condition]
List/Set Comprehension
- 下面 Comprehension 範例有交雜著 tuple 解包。
- couples 本身是無序的 set,所以即使以 list 接收結果,每次跑狀況都會不相同。
couples = {("Totem","Winnie"), ("Robert","May"), ("Tony","Jina")}
ret = [ f'{boy} and {girl}' for boy, girl in couples ]
for couple in ret:
print(couple)
# Robert and May
# Totem and Winnie
# Tony and Jina
Dict Comprehension
- Dict Comprehension 基本上是將 dict 先轉換成其他 list 再來做 Comprehension 操作。
- 例如轉成 <class 'dict_items'> 後再來處理。
dicts = {'A': 'a', 'B': 'b', 'C': 'c', 'D': 'd'}
ret = [f'{k}:{v}' for k, v in dicts.items()]
for d in ret:
print(d)
# A a
# B b
# C c
# D d
Generator Comprehension
- 這邊的名稱命名不是很一致, Generator Comprehension 指的是使用 Comprehension 的句型來建立 Generator。
- 註:
- range(n) 回傳的是一個 generator
- Python Generator 說明
Generator 範例: basic
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def filterEven(numbers: list):
for num in numbers:
if num % 2 == 0:
yield num
evens = filterEven(nums)
print(next(evens)) # 2
print(next(evens)) # 4
print(next(evens)) # 6
Generator Comprehension 範例
- 這個範例完全等同於 basic generator 範例,但你看不到 yield 關鍵字
# 小括號 comprehension 會建立 generator
evens_generator = (num for num in nums if num % 2 == 0)
print(next(evens_generator)) # 2
print(next(evens_generator)) # 4
print(next(evens_generator)) # 6
Nested Comprehension
Nested Comprehension 指的是,槽狀 Comprehension,
結構A: 多重迴圈
寫在越後方的 comprehension 就是越內層的迴圈。結構B: Comprehension 串接
也可以把他想成是 Java 的 Streaming,
把集合的資料連續做多次處理,
把資料串接在另一個 Comprehension 的 in clause 中。
_Nested Comprehension: 多重迴圈範例
- 多維矩陣走訪範例,寫在越後方的 comprehension 就是越內層的迴圈。
table = [
[10, 20, 30],
[11, 21, 31],
[12, 22, 32],
]
unpack = [
cell
for row in table
for cell in row
]
print(unpack)
# [10, 20, 30, 11, 21, 31, 12, 22, 32]
- 多重迴圈範例
# 45乘法表
for i in range(4):
for j in range(5):
print(f'{i} x {j} = '+ str(i * j))
table = [f'{i} x {j} = ' + str(i * j)
for i in range(4) # 先走訪4
for j in range(5) # 先走訪5 (共 4*5 個結果)
]
for t in table:
print(t)
_Nested Comprehension: Java Streaming 範例
- Comprehension 串接成 Java Streaming
- 將前一輪的結果放到次一階段的 in clause 中
- condition 可用來做 filtering
- expression 可用來做 java stream 的 map 動作
class Person:
def __init__(self, name: str, gender: str, waistline: int):
if not isinstance(name, str):
raise TypeError('name should be str')
self.name = name
self.gender = gender
self.waistline = waistline
ps = [
Person('Tom', 'Male', 91),
Person('Michael', 'Male', 89),
Person('Bob', 'Male', 100),
Person('Mary', 'Female', 81),
Person('Winnie', 'Female', 79),
]
# 查出腰圍大於 90 的男性
found = [target.name for target in [man for man in ps if man.gender == 'Male'] if target.waistline > 90]
# Tom, Bob