因此,我尝试将属性动态设置为具有不同名称的类,其中每个属性对我的数据库进行唯一调用。但是,当我访问属性对象时,尽管查找每个具有完全不同值的不同列,但它们都返回相同的结果。这是代码:
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 :(得分:1)
您的错误印象是定义函数会在定义时将函数绑定到变量值。听起来很复杂,抱歉。我试着解释一下。
您正在循环中定义函数(fget
,fset
)。在函数中,您使用循环的变量(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()
答案 1 :(得分: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))