【问题标题】:What is the difference between `vars` and `setattr`?`vars` 和 `setattr` 有什么区别?
【发布时间】:2019-07-20 17:00:40
【问题描述】:

在使用 vars 更改 db.Model(flask-sqlalchemy) 值失败后,我改用 setattr 解决了这个问题,但在阅读 doc 后仍然没有得到 varssetattr 之间的区别。

这是我尝试过的

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 对象时工作正常,但在 modification 中失败(name 没有改变)。

记录/测试

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

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

然后我在函数set_option_parameters中改为setattr(var, option_key, options[option_key])

init 和 modify 都很好用,application.__dict__ 的输出是一样的!

【问题讨论】:

标签: python sqlalchemy


【解决方案1】:

From the docsvars

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

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

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

【讨论】:

    猜你喜欢
    • 2011-11-25
    • 2011-12-19
    • 2010-10-02
    • 2011-12-12
    • 2010-09-16
    • 2012-03-14
    • 2012-02-06
    • 2011-02-25
    • 2011-11-22
    相关资源
    最近更新 更多