gpt4 book ai didi

python - SQLAlchemy 提交对通过 __dict__ 修改的对象的更改

转载 作者:太空狗 更新时间:2023-10-29 21:29:21 24 4
gpt4 key购买 nike

我正在开发一款多人游戏。当我使用 list 中的对象时,它应该使用对象的属性值更新用户生物的统计数据。

这是我的代码:

try:
obj = self._get_obj_by_id(self.query['ObjectID']).first()

# Get user's current creature
cur_creature = self.user.get_current_creature()

# Applying object attributes to user attributes
for attribute in obj.attributes:
cur_creature.__dict__[str(attribute.Name)] += attribute.Value

dbObjs.session.commit()
except (KeyError, AttributeError) as err:
self.query_failed(err)

现在,出于某种原因,这并不能正确地提交内容,所以我尝试了:

cur_creature.Health  = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

这行得通,但不是很方便(因为我需要一个大的 if 语句来更新生物的不同统计数据)

所以我尝试了:

cur_creature.__dict__['Health'] = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

我在日志中得到 100,但没有任何变化,所以我尝试了:

cur_creature.__dict__['Health'] = 100
cur_creature.Health = cur_creature.__dict__['Health']
logging.warning(cur_creature.Health)
dbObjs.session.commit()

日志中仍然是“100”,但没有变化,所以我尝试了:

cur_creature.__dict__['Health'] = 100
cur_creature.Health = 100
logging.warning(cur_creature.Health)
dbObjs.session.commit()

它仍然在日志中写入 100,但不会将更改提交到数据库。现在,这很奇怪,因为它只是在工作版本上有所不同,因为它在顶部有这一行:

cur_creature.__dict__['Health'] = 100

总结:如果我直接修改属性,提交工作正常。相反,如果我通过类的字典修改一个属性,那么,无论我之后如何修改它,它都不会将更改提交到数据库。

有什么想法吗?

提前致谢

更新 1:

此外,这会更新数据库中的生命值,但不会更新饥饿值:

cur_creature.__dict__['Hunger'] = 0
cur_creature.Health = 100
cur_creature.Hunger = 0
logging.warning(cur_creature.Health)
dbObjs.session.commit()

因此,一般来说,访问字典对于属性来说不是问题,但是通过字典修改属性会阻止提交对该属性的更改。

更新 2:

作为临时修复,我覆盖了 Creatures 类中的函数 __set_item__(self):

def __setitem__(self, key, value):
if key == "Health":
self.Health = value
elif key == "Hunger":
self.Hunger = value

因此“使用对象”的新代码是:

try:
obj = self._get_obj_by_id(self.query['ObjectID']).first()

# Get user's current creature
cur_creature = self.user.get_current_creature()

# Applying object attributes to user attributes
for attribute in obj.attributes:
cur_creature[str(attribute.Name)] += attribute.Value

dbObjs.session.commit()
except (KeyError, AttributeError) as err:
self.query_failed(err)

更新 3:

通过查看答案中的建议,我确定了这个解决方案:

Creatures

def __setitem__(self, key, value):
if key in self.__dict__:
setattr(self, key, value)
else:
raise KeyError(key)

另一种方法

 # Applying object attributes to user attributes
for attribute in obj.attributes:
cur_creature[str(attribute.Name)] += attribute.Value

最佳答案

问题不在 SQLAlchemy 中,而是由 Python 的 descriptors mechanism 引起的。每个 Column 属性都是一个描述符:这就是 SQLAlchemy 如何“ Hook ”属性检索和修改以产生数据库请求。

让我们尝试一个更简单的例子:

class Desc(object):
def __get__(self, obj, type=None):
print '__get__'
def __set__(self, obj, value):
print '__set__'

class A(object):
desc = Desc()

a = A()
a.desc # prints '__get__'
a.desc = 2 # prints '__set__'

但是,如果您通过a instance 字典并为'desc' 设置另一个值,您将绕过描述符协议(protocol)(参见 Invoking Descriptors ):

a.__dict__['desc'] = 0  # Does not print anything !

在这里,我们刚刚创建了一个名为 'desc' 的新instance 属性,其值为 0。Desc.__set__ 方法从来没有调用,在您的情况下,SQLAlchemy 将没有机会“捕获”该分配。

解决方案是使用 setattr ,这完全等同于编写 a.desc:

setattr(a, 'desc', 1)   # Prints '__set__'

关于python - SQLAlchemy 提交对通过 __dict__ 修改的对象的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17013965/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com