2017-03-06 138 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))