我玩了一下使用Python API的sqlite3的,我有店面语言一张小桌子与ID,姓名和CREATION_DATE领域。 我试图映射原始查询结果为namedtuple
作为文档推荐,这种方式我可以在一个更可读的方式管理行,所以这里是我的namedtuple
。
LanguageRecord = namedtuple('LanguageRecord', 'id, name, creation_date')
该文档建议该映射的代码如下:
for language in map(LanguageRecord._make, c.fetchall()):
# do something with languages
这是罚款时,我要回的语言,但在这种情况下,我只想找回一种语言的集合:
c.execute('SELECT * FROM language WHERE name=?', (name,))
所以,我的第一次尝试是这样的:
language = map(LanguageRecord._make, c.fetchone())
此代码不工作,因为fetchone()
返回一个元组,而不是一个元组的列表,所以map
函数试图创建三个namedtuples
一个每个元组领域的思想。
我的第一个解决这个方法是明确创建一个列表,并追加到它的元组的结果,是这样的:
languages = []
languages.append(c.fetchone())
for language in map(LanguageRecord._make, languages):
# do something with language
我的第二个方法是使用fetchall()
虽然我只想要一个记录。 我可以用一组名称字段unique
,才能在数据库约束到garantize只是一个结果。
for language in map(LanguageRecord._make, c.fetchall()):
# do something with languages
另一种方法可以是使用fetchall()[0]
而不unique
约束到garantize只是一个结果。
我的问题是这是解决这个问题最好的和常见的方式,我应该用始终fetchall
保持一个通用的接口,让数据库管理的独特逻辑是什么? 或者我应该明确地创建一个列表,在方法上1? 有没有更简单的方法来完成这项任务?
还有一个更简单的方法! SQLITE3为用户定义的方式“行工厂” 。 这些排工厂采取光标和元组行可以返回它想要的任何类型的对象。
一旦你设置行工厂
con.row_factory = my_row_factory
然后用光标返回的行会的结果my_row_factory
施加到元组行。 例如,
import sqlite3
import collections
LanguageRecord = collections.namedtuple('LanguageRecord', 'id name creation_date')
def namedtuple_factory(cursor, row):
return LanguageRecord(*row)
con = sqlite3.connect(":memory:")
con.row_factory = namedtuple_factory
cur = con.cursor()
cur.execute("select 1,2,3")
print(cur.fetchone())
产量
LanguageRecord(id=1, name=2, creation_date=3)
对于如何定义namedtuple工厂另一个例子,看到这个帖子 。
顺便说一句,如果你设置
conn.row_factory = sqlite3.Row
然后行返回类型的字典,它的键是表的列名。 因此,而不是访问的东西,如namedtuple的部分row.creation_date
你可以只使用内置的sqlite3.Row
排工厂,并与访问相当于row['creation_date']
改进row_factory
其实这是,它可以用于各种查询的可重复使用:
from collections import namedtuple
def namedtuple_factory(cursor, row):
"""Returns sqlite rows as named tuples."""
fields = [col[0] for col in cursor.description]
Row = namedtuple("Row", fields)
return Row(*row)
conn = sqlite3.connect(":memory:")
conn.row_factory = namedtuple_factory
cur = con.cursor()
我认为最好使用for language in map(LanguageRecord._make, c.fetchall()[:1]):
因为它可能会导致IndexError与使用fetchall()[0]。
如果你需要一个结果,并且已经有“WHERE”中查询。 据我了解查询应返回一行。 早期的优化是邪恶的。 :)