早期 continue / break でループ内ネスト解消
ループの中で「対象なら…さらに条件を満たすなら…」と if を重ねると、関数全体の早期 return が使えないぶん深いネストになりやすい。対象外の要素は continue で次へ飛ばし、続行できなくなったら break で打ち切る。ガード節の発想をループに持ち込めば、本処理がフラットに並ぶ。
01 月次決算での経費仕訳の一括計上
def post_monthly_expenses(expenses: list[Expense], ledger: Ledger) -> None:
for expense in expenses:
if expense.status is Status.APPROVED:
if expense.has_receipt:
if not expense.is_posted:
ledger.post(expense)def post_monthly_expenses(expenses: list[Expense], ledger: Ledger) -> None:
for expense in expenses:
if expense.status is not Status.APPROVED:
continue
if not expense.has_receipt:
continue
if expense.is_posted:
continue
ledger.post(expense)continue は「この要素はここで終わり、次へ」という早期 return のループ版。スキップ条件を1行単位で追加・削除できるので、「証憑なしでも1万円未満は計上可」のような仕様変更にも対応しやすい。
02 入金の消込 — 古い請求から充当して残額が尽きたら終了
def apply_deposit(deposit: int, invoices: list[Invoice]) -> int:
remaining = deposit
for invoice in sorted(invoices, key=lambda i: i.due_date):
if remaining > 0:
if not invoice.is_paid:
applied = min(remaining, invoice.balance)
invoice.apply(applied)
remaining -= applied
return remainingdef apply_deposit(deposit: int, invoices: list[Invoice]) -> int:
remaining = deposit
for invoice in sorted(invoices, key=lambda i: i.due_date):
if remaining == 0:
break
if invoice.is_paid:
continue
applied = min(remaining, invoice.balance)
invoice.apply(applied)
remaining -= applied
return remaining「この先の要素を処理する意味がなくなった」瞬間に break で抜けるのがポイント。終了条件がループ先頭に明示されるので、フラグ変数で終了を管理するよりも追跡しやすい。