【问题标题】:Different functions, same result不同的功能,相同的结果
【发布时间】:2017-03-06 10:26:23
【问题描述】:

因此,我尝试将属性动态设置为具有不同名称的类,其中每个属性都对我的数据库进行唯一调用。但是,当我访问属性对象时,尽管查找具有完全不同值的不同列,但它们都返回相同的结果。代码如下:

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?是Configs 吗? x.name 的值在哪里设置?
  • x 是一个简单的对象,具有单个 name 属性,该属性具有预分配的字符串。我在代码的另一部分构建这些对象。 configs 只是一个包含 3 个或更多这些对象的列表。
  • 所以您尝试设置一个属性,称为x.name 的值,在访问数据库时从数据库读取和写入?像一个活跃的记录?
  • 不是真的,我正在尝试创建一个属性来调用数据库并在访问时返回一个值,我还可以使用简单的赋值语法更新数据库。
  • 这不是我说的吗?

标签: python setattr


【解决方案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()

【讨论】:

    【解决方案2】:

    如果我按照您要执行的操作进行操作,那么您是非常正确的,当调用您的属性时,它们将使用 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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-01
      • 2021-05-04
      • 1970-01-01
      • 2019-01-12
      • 2020-03-03
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      相关资源
      最近更新 更多