📚 collections.namedtuple 學習指南
命名元組(namedtuple
)是 Python collections
模塊中一種增強型元組,支持通過字段名訪問元素,同時保持元組的內存效率和不可變性。
一、基礎用法
1. 定義命名元組
from collections import namedtuple# 定義 Point 類型(字段名用空格或列表分隔)
Point = namedtuple('Point', ['x', 'y'])
# 或簡寫為
Point = namedtuple('Point', 'x y')# 實例化對象
p = Point(10, y=20) # 類似常規元組或類構造
print(p) # 輸出: Point(x=10, y=20)
2. 訪問元素
print(p.x) # 10(通過字段名)
print(p[0]) # 10(通過索引,保留元組特性)
二、核心特性
1. 不可變性
命名元組繼承自普通元組,元素不可修改:
# 以下操作會報錯
p.x = 100 # AttributeError: can't set attribute
2. 輕量級類替代
相比傳統類,命名元組更簡潔:
# 等價于以下類定義
class PointClass:def __init__(self, x, y):self.x = xself.y = y
三、方法與屬性
1. 常用方法
方法 | 功能 | 示例 |
---|---|---|
_asdict() | 轉為 OrderedDict | p._asdict() → {'x':10, 'y':20} |
_replace(**kwargs) | 創建新實例并替換字段值 | p._replace(x=100) → Point(x=100, y=20) |
_make(iterable) | 通過可迭代對象創建實例 | Point._make([30, 40]) → Point(x=30, y=40) |
2. 元數據屬性
print(p._fields) # 輸出字段名元組: ('x', 'y')# 可擴展新類型(通過繼承)
Point3D = namedtuple('Point3D', Point._fields + ('z',))
四、進階應用
1. 字典互轉
# 轉字典(Python 3.7+ 返回普通字典)
d = p._asdict() # {'x': 10, 'y': 20}# 從字典創建
data = {'x': 30, 'y': 40}
p_new = Point(**data) # Point(x=30, y=40)
2. 默認值與可選參數
通過定義子類添加默認值:
class PointDefault(Point):__slots__ = ()def __new__(cls, x=0, y=0):return super().__new__(cls, x, y)p_default = PointDefault() # Point(x=0, y=0)
3. 添加方法
class PointWithMethods(Point):def distance(self, other):return ((self.x - other.x)**2 + (self.y - other.y)**2)**0.5p1 = PointWithMethods(1, 2)
p2 = PointWithMethods(4, 6)
print(p1.distance(p2)) # 輸出 5.0
五、實際應用場景
1. 數據庫查詢結果
import sqlite3conn = sqlite3.connect('example.db')
cursor = conn.cursor()
cursor.execute('SELECT id, name, age FROM users')# 將每行轉為命名元組
User = namedtuple('User', 'id name age', module=__name__)
users = [User(*row) for row in cursor.fetchall()]print(users[0].name) # 通過字段名訪問數據
2. CSV 文件解析
import csvwith open('data.csv') as f:reader = csv.reader(f)header = next(reader)Row = namedtuple('Row', header)for r in reader:row = Row(*r)print(row.date, row.value) # 按字段名訪問列
3. 替代簡單類
# 表示 RGB 顏色
Color = namedtuple('Color', 'red green blue')
white = Color(255, 255, 255)# 函數返回多個命名值
def get_dimensions():return namedtuple('Size', 'width height')(1920, 1080)screen = get_dimensions()
print(f"分辨率: {screen.width}x{screen.height}")
六、命名元組 vs 其他數據結構
特性 | 命名元組 | 字典 | 普通類 |
---|---|---|---|
內存占用 | 小 | 較大 | 較大 |
訪問速度 | 快速(通過索引和字段名) | 略慢(哈希查找) | 略慢(屬性訪問) |
可變性 | 不可變 | 可變 | 可變 |
語法簡潔性 | 高 | 高 | 低(需定義類) |
代碼可讀性 | 高(明確字段名) | 一般 | 高 |
七、注意事項
1. 字段名規范
- 字段名不能是 Python 關鍵字(如
class
,def
)。 - 字段名不可重復,否則報錯:
# 錯誤示例 Invalid = namedtuple('Invalid', 'x x') # ValueError: 重復字段名
2. 不可變性的權衡
- 優點:線程安全、哈希可用性(可作為字典鍵)。
- 缺點:需要創建新實例以實現“修改”。
八、總結
命名元組是以下場景的理想選擇:
- 需要輕量級不可變數據結構。
- 希望通過字段名提高代碼可讀性。
- 需將數據作為字典鍵使用(普通字典鍵需用元組)。
進一步學習:
- Python 官方文檔 - namedtuple
- 探索
typing.NamedTuple
(Python 3.6+)以支持類型注解!