Python 課程 – 資料結構:字串(str)
建立、索引、切片
簡介
字串(str)是程式設計中最常見的資料型別之一,無論是讀取使用者輸入、處理檔案內容,或是與外部 API 交換資料,都離不開字串的操作。
在 Python 中,字串不僅支援 Unicode,還提供了直觀且功能強大的索引與切片機制,讓開發者可以以簡潔的語法完成複雜的文字處理。
本篇文章將從 字串的建立、索引、切片 三個核心概念出發,結合實務範例說明其使用方式,並探討常見的陷阱與最佳實踐,最後提供幾個在日常開發中常見的應用情境,幫助讀者快速上手並寫出可靠、可讀性高的程式碼。
核心概念
1. 字串的建立
在 Python 中,字串可以使用單引號 (')、雙引號 (") 或三引號 ('''、""") 包起來。
三引號常用於 多行文字 或 文件說明文字(docstring)。
# 單行字串
s1 = 'Hello, World!'
s2 = "Python is fun"
# 多行字串(保留換行與縮排)
s3 = """這是一段
跨越多行的文字,
可以直接寫在程式碼裡。"""
# 使用 raw string(避免跳脫字元被解譯)
path = r'C:\Users\Alice\Documents\file.txt'
- 提示:若字串中同時需要單引號與雙引號,可交替使用或搭配跳脫字元(
\)避免語法錯誤。
quote = "She said, \"It's a beautiful day!\""
2. 字串的索引(Indexing)
字串是 不可變(immutable) 的序列,意味著每個字元都有固定的位置(索引),且索引從 0 開始。
使用方括號 [] 即可取得單一字元。
msg = "Python 3.11"
first_char = msg[0] # 'P'
last_char = msg[-1] # '1'(負索引從尾端開始算起)
second_last = msg[-2] # '1'
2.1 取出子字元時的常見錯誤
- 索引超出範圍:
msg[100]會拋出IndexError。 - 負索引過大:
msg[-100]同樣會拋出IndexError。
解決方式:先檢查字串長度,或使用 try/except 捕捉例外。
try:
ch = msg[100]
except IndexError:
ch = None # 或者給一個預設值
3. 字串的切片(Slicing)
切片讓你一次取得 連續的子字串,語法為 string[start:stop:step],其中:
| 參數 | 含義 | 預設值 |
|---|---|---|
start |
起始索引(包含),可為負數 | 0 |
stop |
結束索引(不包含),可為負數 | 字串長度 |
step |
步長(正向或負向),若為負則反向 | 1 |
3.1 基本切片範例
txt = "abcdefghij"
# 取得第 2~5 個字元(索引 1~4)
sub1 = txt[1:5] # 'bcde'
# 省略 start,從開頭到第 4 個字元(不含第 4 個)
sub2 = txt[:4] # 'abcd'
# 省略 stop,從第 5 個字元到結尾
sub3 = txt[4:] # 'efghij'
# 設定 step 為 2,取出每隔一個的字元
sub4 = txt[::2] # 'acegi'
# 反向切片,取得字串反轉
rev = txt[::-1] # 'jihgfedcba'
3.2 使用負索引與步長
# 取出倒數第 3 到倒數第 1 個字元(不含倒數第 0 個)
sub5 = txt[-3:-0] # 'ij'(-0 等同於 0)
# 反向切片,從倒數第 1 個往前取三個字元
sub6 = txt[-1:-4:-1] # 'jih'
3.3 切片的「深拷貝」概念
由於字串是不可變物件,切片本身不會產生 引用問題。
即使你對切片結果再做修改(實際上是產生新字串),原字串仍保持不變:
original = "2023-08-15"
date_part = original[:10] # '2023-08-15'
# 嘗試改變 date_part(實際上是建立新字串)
date_part = date_part.replace('-', '/')
# original 仍是原本的內容
print(original) # 2023-08-15
常見陷阱與最佳實踐
| 陷阱 | 說明 | 最佳做法 |
|---|---|---|
| 忘記字串不可變 | 直接修改字串會拋出錯誤,或不會改變原字串 | 使用 replace()、join() 等產生新字串 |
| 切片步長為 0 | string[::0] 會產生 ValueError |
步長必須是非零整數 |
| 負索引與切片起止混淆 | s[-1:0] 會得到空字串,因為 stop 必須在 start 之後(正向切片) |
反向切片時使用負步長 s[-1:0:-1] |
使用 + 連接大量字串 |
會產生大量臨時字串,效能低 | 使用 ''.join(list_of_strings) |
| 忽略 Unicode 正規化 | 不同編碼形式的相同字元會被視為不同字串 | 使用 unicodedata.normalize() 統一編碼 |
小技巧
- 快速檢查子字串是否存在:
if "abc" in s: - 取得字串長度:
len(s),配合切片可避免 IndexError。 - 字串格式化:
f"{name}: {value:.2f}"比%或format()更直觀。
實際應用場景
日誌檔案分析
讀取一行日誌後,只取出時間戳記與訊息等關鍵資訊:line = "2023-08-15 14:23:07,123 - INFO - Process started" timestamp = line[:23] # '2023-08-15 14:23:07,123' level = line[26:30] # 'INFO' message = line[33:] # 'Process started'CSV 檔案欄位切割
假設每個欄位長度固定,可直接使用切片取得:row = "John Doe 03011990M" first_name = row[0:8].strip() # 'John' last_name = row[8:16].strip() # 'Doe' birthday = row[16:24] # '03011990' gender = row[24] # 'M'網址參數解析
從 URL 中抽取 query string:url = "https://example.com/search?q=python+string&lang=zh-TW" query_part = url.split('?')[1] # 'q=python+string&lang=zh-TW' params = dict(p.split('=') for p in query_part.split('&')) # {'q': 'python+string', 'lang': 'zh-TW'}文字加密/解密(簡易 Caesar Cipher)
使用切片與步長實作字母位移:import string alphabet = string.ascii_lowercase shift = 3 # 建立加密映射表 trans = str.maketrans(alphabet, alphabet[shift:] + alphabet[:shift]) def caesar_encrypt(text): return text.lower().translate(trans) print(caesar_encrypt("hello world")) # khoor zruog反向顯示密碼
為了 UI 安全,顯示最後四位,其餘以星號取代:pwd = "Abcdef123456" masked = '*' * (len(pwd) - 4) + pwd[-4:] print(masked) # ********3456
總結
字串是 Python 最基礎、同時也是最強大的資料結構之一。透過 建立、索引、切片 三個核心操作,我們可以:
- 快速取得任意子字元或子字串,不必使用迴圈或額外函式。
- 以簡潔的語法完成文字切割、反轉、抽取固定寬度欄位,提升程式可讀性與維護性。
- 避免常見的 IndexError、ValueError,並遵循最佳實踐(如使用
join、Unicode 正規化),寫出更安全、效能更佳的程式。
掌握這些技巧後,無論是日誌分析、檔案處理、網路爬蟲,或是簡易的加密演算法,都能以最少的程式碼完成高品質的文字處理工作。希望本篇文章能成為你在 Python 路上不可或缺的參考手冊,持續練習、探索更進階的字串方法(如正規表示式、re 模組),讓程式碼更具表現力與彈性。祝你玩得開心,寫程式更順手!