2017-03-06 145 views
1

所以我試圖動態地設置屬性到不同名稱的類,其中每個屬性對我的數據庫進行獨特的調用。但是,當我訪問屬性對象時,儘管在不同的列上查看了各自完全不同的值,但它們都返回相同的結果。下面是代碼:不同的功能,相同的結果

class Configs: 

    def __init__(self, guild_id): 
     self.guild_id = guild_id 

for x in configs: 

    def fget(self): 
     return cur.execute(f'SELECT {x.name} FROM configs WHERE guild_id = ?', (self.guild_id,)).fetchone()[0], x.name 

    def fset(self, value): 
     cur.execute(f'UPDATE configs SET {x.name} = ? WHERE guild_id = ?', (value, self.guild_id)) 
     con.commit() 

    setattr(Configs, x.name, property(fget, fset)) 

的CONFIGS變量是對象的列表,其中每個對象具有一個name屬性,它指向一個字符串。結果始終是configs數組的最後一個元素產生的結果,我懷疑這是因爲x.name用於調用,一旦for循環完成,x仍然是數組的最後一個元素。

+0

什麼是'x'?它是一個'Configs'嗎?你在哪裏設置'x.name'的值? – khelwood

+1

'x'是一個簡單的對象,帶有一個'name'屬性,它有一個預先分配給它的字符串。我在代碼的另一部分構建這些對象。 'configs'只是一個包含3個或更多這些對象的列表。 – Exa

+0

所以你試圖設置一個屬性,稱爲「x.name」的值,它在訪問數據庫時從數據庫中讀取和寫入?像一個活躍的記錄? – khelwood

回答

1

你有一種錯誤的印象,即定義一個函數將函數綁定到定義時的變量值。這聽起來很複雜,對不起。我會盡力解釋。

您正在循環中定義函數(fgetfset)。在函數中使用循環變量(x)。這會起作用,但不會以你期望的方式工作。所有函數將完全相同,在調用時總是訪問全局變量x的值。定義時的價值不會被考慮在內。

例如見這樣的:

a = [] 
for i in range(3): 
    def f(): return i 
    a.append(f) 

a[0]() # will return 2 
del i 
a[0]() # will raise a NameError because there is no i anymore 

解決您的問題,您需要在定義成函數的時候通過值:

def fget(self, x=x): 
    return cur.execute(f'SELECT {x.name} FROM configs WHERE guild_id = ?', (self.guild_id,)).fetchone()[0], x.name 

def fset(self, value, x=x): 
    cur.execute(f'UPDATE configs SET {x.name} = ? WHERE guild_id = ?', (value, self.guild_id)) 
    con.commit() 
0

如果我遵循你正在嘗試做的事情,那麼當你的屬性被調用時,他們會使用任何當前的值x.name(這將是在結束時剩下的任何東西)你的循環)。

以下是解決該問題的一種可能方法:將x.name分配給您的屬性功能可以訪問的另一個變量。默認參數可能適用於此。

for x in configs: 

    def fget(self, col_name=x.name): 
     return cur.execute(f'SELECT {col_name} FROM configs WHERE guild_id = ?', (self.guild_id,)).fetchone()[0], col_name 

    def fset(self, value, col_name=x.name): 
     cur.execute(f'UPDATE configs SET {col_name} = ? WHERE guild_id = ?', (value, self.guild_id)) 
     con.commit() 

    setattr(Configs, x.name, property(fget, fset))