【问题标题】:Easier way to read sqlite3 row into object?将 sqlite3 行读入对象的更简单方法?
【发布时间】:2018-10-15 19:19:42
【问题描述】:

在 Python 中,我将 sqlite3 中的行读取到一个简单数据结构的对象中。在分配的那一刻,我必须将行分配给一系列变量。有没有办法以更简单的方式做到这一点?

我在下面包含了一些示例代码,希望能说明我的问题。

import sqlite3

class studentDef(object):
    def __init__(self):
        self.firstName = 'x'
        self.lastName  = 'x'
        self.id        = 'x'
        self.address1  = 'x'
        self.address2  = 'x'
        self.city      = 'x'
        self.state     = 'x'
        self.zip       = 'x'
        self.status    = 0

def main():
    mystudent = studentDef()
    db        = sqlite3.connect('students.sqlite3')
    cursor    = db.cursor()
    selectTxt = "select * from students where status = 1"
    cursor.execute(selectTxt)
    rows = cursor.fetchall()
    for index in range(0,len(rows)):
        mystudent.firstName, mystudent.lastName, mystudent.id, mystudent.address1, \
            mystudent.address2, mystudent.city, mystudent.state, mystudent.zip, \
            mystudent.status = row[index]
        processStudent(mystudent)

if __name__ == '__main__':
    main()

我当前的代码正在阅读 50 多列,并且赋值语句变得有点毛茸茸!由于我仍在开发中,所以在添加、删除或修改列时,我经常弄乱赋值语句。

有没有更简单的方法来做类似的事情:

mystudent = row[index]

我的另一个问题是我在大约 5 个其他程序中这样做。所以每次我更改数据库布局时,我都会花费大量时间来更新我的所有代码。

【问题讨论】:

    标签: python sqlite


    【解决方案1】:

    问题在于您如何编写类初始化程序。一个类应该负责设置自己的数据;编写一个将属性设置为保存值然后依靠类外部的过程将它们设置为实际值的初始化函数是没有意义的。所以:

    class studentDef(object):
        def __init__(self, firstName, lastName, id, address1, address2, city, state, zip, status):
            self.firstName = firstName
            self.lastName  = lastName
            self.id        = id
            self.address1  = address1
            self.address2  = address2
            self.city      = city
            self.state     = state
            self.zip       = zip
            self.status    = status
    

    现在您可以只传入行,使用* 语法将列表展开为单独的参数:

    cursor.execute(selectTxt)
    for row in cursor:
       mystudent = studentDef(*row)
    

    (注意,在 Python 中,您几乎应该从不迭代 range(len(something)),始终迭代事物本身。)

    听起来processStudent 也应该是 studentDef 类的方法。最后,注意 Python 风格是对类使用 InitialCaps,对属性使用 lower_case_with_underscore:StudentDef、first_name、last_name。

    【讨论】:

    • 这绝对是完美的!非常感谢!我想我的 FORTRAN77 正在显示!我从没想过每次都重新实例化该对象。也感谢其他提示!
    【解决方案2】:

    您可以使用对象关系映射 (ORM) 工具。这样的工具会将您的 SQLite3 数据库映射到 Python 对象(反之亦然),从而减少代码量。

    这里是一个使用peewee的例子:

    from peewee import *
    
    db = SqliteDatabase('students.sqlite3')
    
    class Student(Model):
        first_name = CharField()
        last_name = CharField()
        address1 = CharField()
        address2 = CharField()
        city = CharField()
        state = CharField()
        zip = CharField()
        status = SmallIntegerField()
    
        class Meta:
            database = db
    

    然后您可以使用以下方法查询您的学生:

    >>> query = Student.select()
    >>> [student.first_name for student in query]
    ['Charlie', 'Huey', 'Peewee']
    >>> query[1]
    <__main__.Student at 0x7f83e80f5550>
    >>> query[1].first_name
    'Huey'
    

    还有其他与 SQLite 兼容的 Python ORM:SQLAlchemyDjango 模型(用于构建 Web 应用程序),可能还有很多其他的。

    【讨论】:

      猜你喜欢
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-24
      • 2023-04-04
      相关资源
      最近更新 更多