Python sqlite3.Row.__getitem__ 方法
上次修改时间:2025 年 4 月 15 日
本综合指南探讨了 Python 的 sqlite3.Row.__getitem__
方法,该方法提供了对行值的索引访问。我们将涵盖基本用法、索引选项和实际示例。
基本定义
sqlite3.Row.__getitem__
方法允许通过索引或列名访问行值。它是基于索引和基于名称的行数据访问的底层实现。
主要特点:它支持用于位置访问的整数索引和用于列名访问的字符串键。当在 Row 对象上使用方括号表示法时,它在内部使用。
基本行访问
这是 __getitem__
的最简单用法,可以通过索引和列名访问行值。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute('''CREATE TABLE users (id INTEGER, name TEXT)''') cursor.execute("INSERT INTO users VALUES (1, 'Alice')") cursor.execute("SELECT * FROM users") row = cursor.fetchone() # Access by index print(row.__getitem__(0)) # 1 # Access by column name print(row.__getitem__('name')) # Alice
此示例显示了使用 __getitem__
基于索引和基于名称的访问。 row_factory
设置为 sqlite3.Row
以进行命名访问。
通常,你会使用 row[0]
或 row['name']
语法,这些语法在内部调用 __getitem__
。
访问多个列
此示例演示了如何在循环中使用 __getitem__
访问多个列。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute('''CREATE TABLE products (id INTEGER, name TEXT, price REAL)''') cursor.execute("INSERT INTO products VALUES (1, 'Laptop', 999.99)") cursor.execute("SELECT * FROM products") row = cursor.fetchone() # Access all columns by name for col in row.keys(): print(f"{col}: {row.__getitem__(col)}")
该示例展示了如何遍历所有列并使用 __getitem__
和列名访问它们的值。 keys
方法提供列名。
当你需要处理所有列而事先不知道它们的名称时,此模式非常有用。
处理缺失的列
此示例显示了尝试使用 __getitem__
访问不存在的列时会发生什么。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute('''CREATE TABLE test (id INTEGER)''') cursor.execute("INSERT INTO test VALUES (1)") cursor.execute("SELECT * FROM test") row = cursor.fetchone() try: # Access non-existent column print(row.__getitem__('nonexistent')) except IndexError as e: print(f"Error: {e}")
尝试使用 __getitem__
访问不存在的列会引发 IndexError
。此行为与 Python 的序列协议一致。
在处理动态查询时,始终使用 keys
检查列是否存在或处理潜在的异常。
与整数索引一起使用
此示例演示了如何将 __getitem__
与整数索引一起使用以进行位置访问。
import sqlite3 with sqlite3.connect(':memory:') as conn: cursor = conn.cursor() cursor.execute('''CREATE TABLE data (a INTEGER, b INTEGER, c INTEGER)''') cursor.execute("INSERT INTO data VALUES (10, 20, 30)") cursor.execute("SELECT * FROM data") row = cursor.fetchone() # Access by position print(row.__getitem__(0)) # 10 print(row.__getitem__(2)) # 30 # Negative indices work too print(row.__getitem__(-1)) # 30
该示例显示了使用整数索引的标准序列样式访问。负索引按预期工作,从末尾开始计数。
位置访问比命名访问更快,但可读性较差,尤其是在列很多的情况下。
与其他 Row 方法结合使用
此示例显示了 __getitem__
如何与其他 Row 方法(如 keys
和 values
)交互。
import sqlite3 with sqlite3.connect(':memory:') as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute('''CREATE TABLE events (id INTEGER, name TEXT, date TEXT)''') cursor.execute("INSERT INTO events VALUES (1, 'Meeting', '2025-01-01')") cursor.execute("SELECT * FROM events") row = cursor.fetchone() # Combine with keys() and values() for i, col in enumerate(row.keys()): print(f"{col}: {row.__getitem__(i)} == {row.__getitem__(col)}")
该示例演示了当引用同一列时,基于索引和基于名称的访问返回相同的值。顺序与查询的列顺序匹配。
这种一致性在构建动态数据处理管道时非常重要。
性能比较
此示例比较了 __getitem__
与直接属性访问的性能。
import sqlite3 import timeit with sqlite3.connect(':memory:') as conn: conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute('''CREATE TABLE perf (a INTEGER, b INTEGER)''') cursor.execute("INSERT INTO perf VALUES (1, 2)") cursor.execute("SELECT * FROM perf") row = cursor.fetchone() # Time __getitem__ access t1 = timeit.timeit(lambda: row.__getitem__('a'), number=100000) # Time direct attribute access t2 = timeit.timeit(lambda: row['a'], number=100000) print(f"__getitem__: {t1:.3f}s") print(f"Direct access: {t2:.3f}s")
该示例表明,直接方括号访问 (row['a']
) 比直接调用 __getitem__
略快。这两种方法都非常有效。
在大多数应用程序中,性能差异可以忽略不计,因此更喜欢更具可读性的语法。
自定义 Row 子类
此高级示例演示了如何创建扩展 __getitem__
行为的自定义 Row 子类。
import sqlite3 class CustomRow(sqlite3.Row): def __getitem__(self, key): val = super().__getitem__(key) return f"Custom: {val}" with sqlite3.connect(':memory:') as conn: conn.row_factory = CustomRow cursor = conn.cursor() cursor.execute('''CREATE TABLE items (id INTEGER, name TEXT)''') cursor.execute("INSERT INTO items VALUES (1, 'Widget')") cursor.execute("SELECT * FROM items") row = cursor.fetchone() print(row.__getitem__('name')) # Custom: Widget print(row['id']) # Custom: 1
该示例展示了如何子类化 sqlite3.Row
并修改 __getitem__
行为。所有访问方法都继承了新行为。
此技术对于向行访问操作添加验证、转换或日志记录非常强大。
最佳实践
- 首选命名访问: 使用列名以提高可读性
- 处理缺失的列: 使用 keys() 检查或捕获异常
- 使用直接语法: 首选 row['name'] 而不是 __getitem__
- 考虑性能: 位置访问更快
- 记录列顺序: 当使用位置访问时
资料来源
作者
列出所有 Python 教程。