str.index() 與 str.find() 功能相似,皆回傳子字串首次出現的索引。關鍵差別在於:**找不到時 index() 拋出 ValueError 異常**,而 find() 回傳 -1。本文詳細說明語法、參數、異常處理模式、適用場景與最佳實踐。
str.index(sub[, start[, end]]) -> int
ValueError: substring not found。
text = "abcdefghijklmnop"
print(text.index("def")) # 3
print(text.index("def", 4)) # ValueError (從索引 4 開始找不到)
print(text.index("xyz")) # ValueError
find vs index| 特性 | find() | index() |
|---|---|---|
| 找到時 | 回傳索引 | 回傳索引 |
| 找不到時 | 回傳 -1 | 拋 ValueError |
| 適用邏輯 | 條件判斷、可選搜尋 | 斷言必須存在、契約式設計 |
| 效能 | 相同 (C 層實現) | 相同 |
def find_mandatory(text, keyword):
try:
return text.index(keyword)
except ValueError:
raise ValueError(f"必要關鍵字 '{keyword}' 不存在於文本中")
# 使用
pos = find_mandatory("error: disk full", "error:") # 0
# pos = find_mandatory("warning: low mem", "error:") # 拋出自訂異常
in 判斷再呼叫(避免異常開銷)
if keyword in text:
pos = text.index(keyword) # 保證不會拋異常
else:
handle_missing(keyword)
def safe_index(text, sub, default=-1):
try:
return text.index(sub)
except ValueError:
return default
print(safe_index("abc", "x")) # -1
print(safe_index("abc", "x", None)) # None
start/end 切片搜尋
log = "[2024-01-15 10:30:00] ERROR: Connection timeout"
# 只在括號內找時間格式
start = log.find('[') + 1
end = log.find(']')
timestamp = log[start:end] # "2024-01-15 10:30:00"
# 或直接用 index 限定範圍
# log.index(':', start, end) # 找第一個冒號
index()
lst = ['a', 'b', 'c', 'b']
print(lst.index('b')) # 1
print(lst.index('b', 2)) # 3 (從索引 2 開始找)
# lst.index('x') # ValueError
需要索引位置? ├─ 找不到是「正常情況」 → 用 find(),檢查 != -1 ├─ 找不到是「程式邏輯錯誤/資料不完整」 → 用 index(),讓異常往上拋 └─ 只需判斷存在性 → 用 in 運算子(最快、最清晰)
index() 時務必確認子字串必定存在,或包裝 try/except。index() 參數是**元素**,不支援切片參數 start/end(Python 3.10+ 列表才支援)。index() 比 find() 快,實則相同;異常拋出反而有額外開銷。
import sys
def demo(text, sub):
print(f"Text: {text!r}")
print(f"Sub : {sub!r}")
print(f"find: {text.find(sub)}")
try:
print(f"index: {text.index(sub)}")
except ValueError as e:
print(f"index: ValueError - {e}")
print("-" * 40)
if __name__ == '__main__':
if len(sys.argv) == 3:
demo(sys.argv[1], sys.argv[2])
else:
demo("hello world", "world")
demo("hello world", "python")
demo("abcabc", "bc")
理解 index() 「找不到即異常」的契約語意,能讓代碼意圖更明確:用 find 處理可選搜尋,用 index 斷言必要結構,配合 try/except 在適當層級處理異常,寫出健壯且可維護的字串處理邏輯。