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 教程。