`vars`和`setattr`有什么区别?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (10)

在没有使用变量来改变db.Model(flask-sqlalchemy)值之后,我通过使用setattr来解决它,但是在阅读doc之后仍然没有得到变量和setattr之间的区别。

这是我尝试过的

vars(失败)

代码

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def set_option_parameters(var, option_keys, options):
    for option_key in options:
        if option_key in option_keys and options[option_key] is not None:
            vars(var)[option_key] = options[option_key]
            # setattr(var, option_key, options[option_key])

class Application(db.Model):
    id = db.Column(db.BigInteger(), primary_key=True, autoincrement=True)
    name = db.Column(db.VARCHAR(20), nullable=False)
    ...
    def __init__(self, options):
        option_keys = set(["name"])
        set_option_parameters(self, option_keys, options)

    def modification(self, options):
        modifiable = set(["name"])
        set_option_parameters(self, modifiable, options)

vars(var)[option_key] = options[option_key] 在启动Application对象时工作正常,但失败了modificationname没有改变)。

日志/测试

我试着打印application.__dict__之前db.session.commit(),它确实被修改了!

application = Application.query.filter_by(id=args["id"]).first()
# args["name"] is not None
app.logger.info(f"Before: {application.__dict__}")
application.modification(args)
app.logger.info(f"After: {application.__dict__}")
db.session.commit()

输出

[2019-02-27 11:22:59,209] INFO in equipmentbaseapplicationhandler: Before:{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f718ac2b588>, 'id': 9, 'name': 'old_name'}
[2019-02-27 11:22:59,209] INFO in equipmentbaseapplicationhandler: After:{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x7f718ac2b588>, 'id': 9, 'name': 'new_name'}

但是当我签入mysql时,它无法正常工作

setattr(成功)

然后我改为setattr(var, option_key, options[option_key])功能set_option_parameters

它在init和修改方面都很好用,输出application.__dict__也是一样的!

提问于
用户回答回答于

从文档vars

模块和实例等对象具有可更新的dict属性; 但是,其他对象可能对其dict属性具有写入限制(例如,类使用types.MappingProxyType来防止直接字典更新)。

通过查看SQLAlchemy源代码(例如,这里),返回some_model.__dict__访问时的副本是一种常见的模式,而不是返回__dict__自身。因此,您可能更新副本而不是原始副本。否则,即使dict发生变化,dict也可能被属性本身覆盖。

setattrs 是正确的模式,更明确。

扫码关注云+社区

领取腾讯云代金券