不同的功能,相同的结果
Different functions, same result
所以我正在尝试将属性动态设置为具有不同名称的 class,其中每个 属性 都对我的数据库进行唯一调用。但是,当我访问 属性 对象时,尽管在每个具有完全不同值的不同列上查找,但所有这些对象都 return 相同的结果。这是代码:
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 仍然是数组。
如果我按照你想做的去做,你是完全正确的,当你的属性被调用时,它们将使用 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))
您误以为定义函数会在定义时将函数绑定到变量值。这听起来很复杂,抱歉。我会尽力解释。
您正在循环定义函数(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()
所以我正在尝试将属性动态设置为具有不同名称的 class,其中每个 属性 都对我的数据库进行唯一调用。但是,当我访问 属性 对象时,尽管在每个具有完全不同值的不同列上查找,但所有这些对象都 return 相同的结果。这是代码:
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 仍然是数组。
如果我按照你想做的去做,你是完全正确的,当你的属性被调用时,它们将使用 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))
您误以为定义函数会在定义时将函数绑定到变量值。这听起来很复杂,抱歉。我会尽力解释。
您正在循环定义函数(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()