2014-02-14 70 views
0

我試圖找出如何鏈類的方法來提高一個工具類我已經寫 - 的原因,我不希望進入:)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. 
+0

爲什麼被標記爲「元編程」,爲什麼標題中的「描述符」?在你的問題或任何可能的答案中,似乎沒有任何元編程技術或描述符的用法...... – abarnert

回答

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()什麼?

+0

我不想陷入爲什麼在構造函數中定義遊標的細節中陷入困境, t爲我們的架構工作,長話短說,它不會很好地與我們的自定義sql上下文管理器。 – NFicano

+0

@NFicano:我不是在'CRUD'類的構造函數中定義遊標,而是在'CRUD.cursor'方法中定義遊標,這正是您希望它發生的地方。關鍵是,無論需要什麼狀態,都將存儲在新的'CRUDCursor'對象中,而不是存儲在'CRUD'對象中,以便在調用'cursor'後不會保存在'CRUD'對象中,這是正是你所要求的。 – abarnert