Python 将方法添加到函数返回的类

Python 将方法添加到函数返回的类,python,class,python-3.x,mysql-python,Python,Class,Python 3.x,Mysql Python,免责声明:这个问题与家庭作业有关。我并不期待有一个解决方案,但我希望能更好地理解被问到的问题以及这个家庭作业练习(可能)的效用 这个问题是在一堂关于使用Python的MySQLdb模块以及如何更好地表示结果集(可能还有它的行)而不是元组的元组(MySQLdb默认情况下)的课之后提出的 问题是:修改classFactory.py源代码,使build\u row函数返回的DataRow类具有另一种方法: retrieve(self, curs, condition=None) self(通常)是调

免责声明:这个问题与家庭作业有关。我并不期待有一个解决方案,但我希望能更好地理解被问到的问题以及这个家庭作业练习(可能)的效用

这个问题是在一堂关于使用Python的MySQLdb模块以及如何更好地表示结果集(可能还有它的行)而不是元组的元组(MySQLdb默认情况下)的课之后提出的

问题是:修改classFactory.py源代码,使build\u row函数返回的DataRow类具有另一种方法:

retrieve(self, curs, condition=None)
self(通常)是调用其方法的实例,curs是现有数据库连接上的数据库游标,condition(如果存在)是一个条件字符串,对于所有接收到的行,该字符串必须为true。 检索方法应该是一个生成器,生成结果集的连续行,直到结果集完全耗尽。每一行都应该是DataRow类型的新对象

def build_row(table, cols):
    """Build a class that creates instances of specific rows"""
    class DataRow:
        """Generic data row class, specialized by surrounding function"""
        def __init__(self, data):
            """Uses data and column names to inject attributes"""
            assert len(data)==len(self.cols)
            for colname, dat in zip(self.cols, data):
                setattr(self, colname, dat)
        def __repr__(self):
            return "{0}_record({1})".format(self.table, ", ".join(["{0!r}".format(getattr(self, c)) for c in self.cols]))
    DataRow.table = table
    DataRow.cols = cols.split()
    return DataRow
  • 在函数定义中创建类的目的是什么?这通常是由专业开发人员完成的吗?如果是,有什么好处
  • 为什么数据库游标是
    retrieve
    方法的(显式)参数?数据库游标不应该被引用在此脚本范围之外吗(在建立数据库连接时)
  • (当前)说
    build_row
    函数将接受两个参数-
    table
    cols
    ,并返回一个类似于(例如)“exampleTable_record(fieldA,fieldB,fieldC)”的字符串是否正确
  • 成功添加
    retrieve
    方法后,我希望
    build\u row
    现在返回什么
  • 正如我前面提到的,如果我知道为什么要添加
    retrieve
    方法,那么我可能会更好地知道如何解决这个问题

  • 这被称为工厂设计模式。。。虽然在这种情况下,它只是使类的实例化被强制到包含该类的方法。。。这将强制您在实例化时设置表和列名属性。。。如果在尝试调用检索时未正确实例化,则可能会导致错误
  • Im为了查询数据库,它需要一个游标对象
  • 是的,但是它返回并且DataRow类不是字符串。。。这有一个字符串表示
  • 包含数据的数据行
  • 这里是一个与工厂设计模式讨论的链接

    一个示例检索函数

    @classmethod #if this is a classmethod
    def retrieve(self, curs, condition=None):
            if condition:
               curs.execute("SELECT * FROM {0} WHERE {1}".format(self.table,condition)
            else:
               curs.execute("SELECT * FROM {0}".format(self.table)
            for row in curs.fetchall():
                yield DataRow(row)
    
    然后你会做一些类似的事情

    my_users = build_row("users",["username","password","avatar"])
    my_users = my_users()  #if you need to operate on an instance.... but class method would be better
    #users is the name of a table already in our database, whose columns are username,password, and avatar
    db=sqlite3.connect("some_database.sql")
    for user in my_users.retrieve(db.cursor(),"username='bob'"):
        print user #something like users_record({'username':'bob','password':'123%gw','avatar':None)
        print user.username #bob
        print user.avatar #None
        print user.password #whatever
        print user.blah #Error!!!!
    

    你所拥有的是一个可以专业使用的例子。函数
    build\u row
    是一个类工厂,它返回适合处理特定表和列的数据的类

    虽然我个人不会在这个特定的案例中使用工厂模式,但它确实有效

    为了解释这段代码的作用,它基本上创建了一个类,该类使用函数调用中的表和列。如果您在代码
    self.cols
    self.table
    中注意到,它们实际上不是
    DataRow
    的一部分,那么它们随后会附加到数据行,这显示了以这种方式创建类的灵活性

    build\u row
    函数实际返回的是一个类!此类应用于从数据库获取数据。。。这是您必须为任务构建的部分。您需要在select语句中使用
    table
    (表名),还需要
    cols
    。。。基本上,您的函数(我不会为您编写)应该:

    SELECT <PUT THE `cols` HERE> FROM `table`;
    
    从“表”中选择;
    
    并返回结果。这足够让你走了

    2) 为什么数据库游标是检索方法的(显式)参数?数据库游标不应该被引用在此脚本范围之外吗(在建立数据库连接时)

    封装。依赖全局魔法变量会产生依赖关系,在可能的情况下应该避免这种依赖关系。考虑到您的应用程序可能同时具有多个游标,或者甚至可能通过单独的连接与两个数据库进行对话。
    传入参数还使代码更易于测试:您可以向其传递模拟类或类似的类,而无需修改全局变量。

    您的函数中是否缺少缩进级别?这种情况在Python中非常常见。在这种情况下,我会担心名为“table”或“cols”或“retrieve”的列会覆盖属性,所以我认为这不是一个很好的例子。然而,专业开发人员确实经常编写错误的可利用代码:)(1)好的,这是一种常见的做法;使用工厂设计模式有什么优势?(2) 为什么需要在此函数中调用数据库游标?(4) 您能否提供一个示例(包括伪数据),说明在将
    检索
    方法成功添加到类后将返回什么?您使用的是
    检索
    ,就好像它是一个类方法一样。这是合适的,但问题和答案暗示了一个实例方法。修复了。。。有点。。。但它可能应该是一个类方法