## 1) 兩個核心指標在算什麼
– `count_leaf_params(obj)`:算「所有最底層 scalar(非容器值)」總數。
– `count_level_widths(obj)`:用 BFS 算「每一層有幾個節點」,回傳 tuple。
一句話記憶:
– leaf = 算「總共有幾片葉子」
– widths = 算「每一層有多寬」
## 2) 指定範例
obj = {
"a": {"x": 1, "y": 2},
"b": [3, 4],
}先看最外層 `obj.values()`:
[{"x": 1, "y": 2}, [3, 4]]所以 BFS 第 0 層有 2 個節點。
## 3) `count_level_widths(obj)` 逐步變化(最短版)
初始:
current = [{"x": 1, "y": 2}, [3, 4]]
widths = []第 1 輪 while:
widths.append(len(current)) # widths = [2]
next_level = []展開 `current` 兩個節點:
# item = {"x": 1, "y": 2} -> extend values -> [1, 2]
# item = [3, 4] -> extend list -> [1, 2, 3, 4]
next_level = [1, 2, 3, 4]
current = next_level第 2 輪 while:
widths.append(len(current)) # widths = [2, 4]
next_level = []
# 1,2,3,4 都是 scalar,不再展開
current = []
# current 為空 list(False)時,while current 條件不成立,迴圈結束
# 補充:這裡不是手動清空,而是因為本輪 current 內只有 scalar,
# for 迴圈不會把任何元素加進 next_level,所以 next_level 仍是 [];
# 接著執行 current = next_level,自然就變成空 list。結束:
tuple(widths) == (2, 4)## 4) `count_leaf_params(obj)` 結果
– 葉子是:`1, 2, 3, 4`
– 總數是:`4`
所以:
count_leaf_params(obj) == 4## 5) 可直接貼上的最小 helper
def count_leaf_params(obj):
if isinstance(obj, dict):
return sum(count_leaf_params(v) for v in obj.values())
if isinstance(obj, list):
return sum(count_leaf_params(x) for x in obj)
if isinstance(obj, (tuple, set)):
raise TypeError(
f"count_leaf_params() only accepts JSON-compatible containers (dict/list). "
f"Got non-JSON container: {type(obj).__name__}"
)
return 1
def count_level_widths(obj):
if isinstance(obj, dict):
current = list(obj.values())
elif isinstance(obj, list):
current = list(obj)
elif isinstance(obj, (tuple, set)):
raise TypeError(
f"count_level_widths() only accepts JSON-compatible containers (dict/list). "
f"Got non-JSON container: {type(obj).__name__}"
)
else:
return ()
widths = []
while current:
widths.append(len(current))
next_level = []
for item in current:
if isinstance(item, dict):
next_level.extend(item.values())
elif isinstance(item, list):
next_level.extend(item)
elif isinstance(item, (tuple, set)):
raise TypeError(
f"count_level_widths() only accepts JSON-compatible containers (dict/list). "
f"Got non-JSON container: {type(item).__name__}"
)
current = next_level
return tuple(widths)### 5.1) 俄羅斯娃娃模板(遞迴通用骨架)
def task(state):
# 1) Base Case:最小問題,直接回傳
if is_smallest(state):
return base_answer
# 2) Recursive Step:拆成更小、同型的子問題
children = split(state)
# 3) Combine:整合子問題答案
return combine(task(child) for child in children)對照關係:
– `is_smallest(state)` = 不是容器(scalar)
– `split(state)` = `obj.values()` 或 `obj`
– `combine(…)` = `sum(…)`
### 5.2) 套用模板後的 `count_leaf_params` 寫法
def count_leaf_params(obj):
# 1) Guard:非 JSON container 視為資料異常
if isinstance(obj, (tuple, set)):
raise TypeError(
f"count_leaf_params() only accepts JSON-compatible containers (dict/list). "
f"Got non-JSON container: {type(obj).__name__}"
)
# 2) Base Case:最小問題(非容器)
if not isinstance(obj, (dict, list)):
return 1
# 3) Recursive Step + Combine
if isinstance(obj, dict):
return sum(count_leaf_params(v) for v in obj.values())
return sum(count_leaf_params(x) for x in obj)## 6) 這個範例的最終答案
obj = {
"a": {"x": 1, "y": 2},
"b": [3, 4],
}
count_level_widths(obj) # (2, 4)
count_leaf_params(obj) # 4
推薦hahow線上學習python: https://igrape.net/30afN










近期留言