Python描述符链式方法

时间:2014-02-14 00:24:18

标签: python

我正在试图找出如何链接类方法来改进我一直在写的实用程序类 - 出于我不想进入的原因:)

现在假设我想在类实例上链接一个链类方法(在这种情况下用于设置游标),例如:

# initialize the class instance
db = CRUD(table='users', public_fields=['name', 'username', 'email'])

#the desired interface class_instance.cursor(<cursor>).method(...)
with sql.read_pool.cursor() as c:
    db.cursor(c).get(target='username', where="omarlittle")

令人困惑的部分是我希望在.get(...)被调用并且已经返回之后光标不会作为类属性持久存在,我想要求必须首先调用.cursor(cursor)

class CRUD(object):
    def __init__(self, table, public_fields):
        self.table = table
        self.public_fields = public_fields

    def fields(self):
        return ', '.join([f for f in self.public_fields])

    def get(self, target, where):
        #this is strictly for illustration purposes, I realize all
        #the vulnerabilities this leaves me exposed to.
        query = "SELECT {fields} FROM {table} WHERE {target} = {where}"
        query.format(fields=self.fields, table=self.table, target=target,
                     where=where)
        self.cursor.execute(query)

    def cursor(self, cursor):
        pass  # this is where I get lost.

1 个答案:

答案 0 :(得分:0)

如果我理解你在问什么,你想要的是cursor方法用一个get方法返回一些符合要求的对象。它返回的对象没有理由是self;它可以改为返回某个游标类型的实例。

该实例可以对self进行反向引用,或者它可以获得自己需要作为游标的内部副本的副本,或者它可以是来自知道的低级数据库库的底层对象的包装器如何成为游标。

如果您查看DB API 2.0规范或其实现,例如stdlib的sqlite3,那么他们就是这样做的:DatabaseConnection对象(从顶级connect函数获得的东西)有一个cursor方法返回一个Cursor对象,而Cursor对象有一个execute方法。

所以:

class CRUDCursor(object):
    def __init__(self, c, crud):
        self.crud = crud
        self.cursor = however_you_get_an_actual_sql_cursor(c)

    def get(self, target, where):
        #this is strictly for illustration purposes, I realize all
        #the vulnerabilities this leaves me exposed to.
        query = "SELECT {fields} FROM {table} WHERE {target} = {where}"
        query.format(fields=self.crud.fields, table=self.crud.table, 
                     target=target, where=where)
        self.cursor.execute(query)
        # you may want this to return something as well?

class CRUD(object):
    def __init__(self, table, public_fields):
        self.table = table
        self.public_fields = public_fields

    def fields(self):
        return ', '.join([f for f in self.public_fields])

    # no get method

    def cursor(self, cursor):
        return CRUDCursor(self, cursor)

但是,您的示例似乎仍然存在严重问题。通常,在对游标执行SELECT语句之后,您希望从该游标中获取行。你没有在你的“用户”代码中保留光标对象,并且你明确地不希望CRUD对象保持其光标,所以...你怎么期望这样做?也许get最后应该return self.cursor.fetch_all()或者什么?