簡體   English   中英

`vars` 和 `setattr` 有什么區別?

[英]What is the difference between `vars` and `setattr`?

在使用 vars 更改 db.Model(flask-sqlalchemy) 值失敗后,我改用setattr解決了這個問題,但在閱讀文檔后仍然沒有得到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 和application.__dict__都很好用, application.__dict__的輸出是一樣的!

來自vars的文檔

模塊和實例等對象具有可更新的dict屬性; 但是,其他對象可能對其dict屬性有寫限制(例如,類使用 types.MappingProxyType 來防止直接字典更新)。

查看 SQLAlchemy 源代碼(例如, 這里),在訪問時返回some_model.__dict__的副本是一種常見模式,而不是返回__dict__本身。 因此,您可能正在更新副本而不是原件。 否則,即使 dict 更改,dict 也可能被屬性本身覆蓋。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM