如何优雅地检查对象/实例/变量的存在,如果它存在于python中,同时将其分配给变量?

Posted

技术标签:

【中文标题】如何优雅地检查对象/实例/变量的存在,如果它存在于python中,同时将其分配给变量?【英文标题】:How to elegantly check the existence of an object/instance/variable and simultaneously assign it to variable if it exists in python? 【发布时间】:2011-07-05 19:33:12 【问题描述】:

我正在使用 SQLAlchemy 填充数据库,并且经常需要在处理之前检查数据库中是否存在 orm 对象。这可能是一个非常规的问题,但我发现自己经常遇到这种模式:

my_object = session.query(SomeObject).filter(some_fiter).first()
if my_object: # Mostly in databases...
    # Juchee it exists
    # process
else:
    # It does not exist. :-(
    my_object = SomeObject()
    # process

梦想会是这样的:

if my_object = session.query(someObject).blabla.first():
    # if my_object is None this scope is left alone
    # if my_object is not None I can work with my_object here...

我知道,这种语法是错误的,但我想解释一下,这个例子是什么意思。任何等效的方式都会让我开心。

这种模式有没有优雅的 Python 方法?这个问题不仅针对 SQLAlchemy,还针对每个等效场景。

闭上眼睛点击“发布你的问题”,等待聪明人和 pythonistas 追捕我,因为我问了一些可能不合适的问题 ;-)

【问题讨论】:

显式总是比隐式好,Python 说......我们明白了。一开始我也很沮丧。如此不雅。哦,好吧。 根据PEP 572,我们将在 Python 3.8 中以if my_object := session.query(...): 的形式提供此功能,这几乎正是 OP 所要求的。 【参考方案1】:

您希望执行 Exist 查询以提高效率

(ret, ), = Session.query(exists().where(SomeObject.field==value))

Mike Bayer 在他的博文中解释了这一点:http://techspot.zzzeek.org/2008/09/09/selecting-booleans/

如果您不想将元​​组作为结果,您可以使用标量:

ret = Session.query(exists().where(SomeObject.field==value)).scalar()

【讨论】:

别忘了导入exists():from sqlalchemy import exists 如何检查多个字段?即在 'where' 调用类似 'Someobject.field1==value1 and Someobject.field2==value2' 我找到了。 ret = Session.query(exists().where(and_(Someobject.field1 == value1, Someobject.field2 == value2))) 有没有办法使用动态字段获取数据?例如。 field_name = 'id' 或 field_name = 'email' ret = Session.query(exists().where(SomeObject[field_name]==value)).scalar() 为了使其更通用且不指定类型,可以将其修改为:session.query(exists().where(type(my_object).id == my_object.id)).scalar()【参考方案2】:

很久以前就有人问过这个问题,但对于未来的访问者来说,更简洁的检查方法是

 if session.query(model).filter(some_filter).count():
     # do stuff

【讨论】:

这看起来正是他所要求的。 count() 可能很简洁,但效率也很低——检查 有多少 项匹配过滤器 X 比检查是否 any 更昂贵事物匹配过滤器 X;对于“存在”检查,可以在找到第一个匹配项时声明成功,而不是继续寻找更多匹配项。 什么是model,什么是some_filter? Model 是您要查询的任何模型,而 filter 是您要过滤查询的任何过滤器。【参考方案3】:

将它包装在一个函数上(无耻地从 django get_or_create 窃取,但它不会返回一个元组)

get_or_create(model, **kwargs):
    try:
        # basically check the obj from the db, this syntax might be wrong
        object = session.query(model).filter(**kwargs).first()
        return object
    except DoesNotExistException: # or whatever error/exception it is on SQLA
        object = model()
        # do it here if you want to save the obj to the db
        return object

就是这样。使用它:

obj = get_or_create(SomeObject, filters)

如果需要,将 **kwargs 更改为简单参数(如 some_filters)

尝试包装你经常使用的东西(将它们包装到函数或类中)

这只是伪代码,可能有语法错误。

编辑:强调

【讨论】:

加分点:试着让你的函数告诉你,它给你的对象是来自数据库还是新创建的(提示已经存在:参见 django 的 get_or_create)【参考方案4】:

我知道这不是一步,但这可以接受吗?

my_object = session.query(SomeObject).filter(some_filter).first()
if my_object is None:
    my_object = SomeObject()
#process

【讨论】:

【参考方案5】:
from sqlalchemy.orm.util import has_identity

my_object = session.query(SomeObject).get(id) or SomeObject()
# Processing...

# Check if the object exists in the database
if not has_identity(my_object):
    session.add(my_object)

session.commit()

.get() 可以根据需要替换为 filter() + first()

【讨论】:

【参考方案6】:
if DBSession.query(ObjectType).filter(ObjectType.some_parametter == "This").first() is None:

这是一种有效的单行检查记录是否存在的方法。它是高效的,因为它只抓取第一个对象,并且它可以在一行上,因为 first() 在没有匹配记录时返回 None。希望有帮助!

【讨论】:

我同意。这是超级干净和高效的,无需在 try/exception 块上使用额外的资源。【参考方案7】:

你可以用这个:

sth = session.query.filter_by().first()
if sth is None:
    ....
else:
    ....

我已经测试过了,效果很好。

【讨论】:

【参考方案8】:

这里有一些不错的建议。使用 NoResultFound 异常怎么样?

try:
    existing = dbsession.query(SomeObject).filter_by(value=value).one()
    return existing
except sqlalchemy.orm.exc.NoResultFound:
    obj = SomeObject()

【讨论】:

【参考方案9】:

这是使用 SQLalchemy 检查对象是否存在的函数。

def exists(obj, **kwargs):
    """" if obj filtered by kwargs exist return it otherwise return None
        obj : is the sql alchemy model object which existence is being checked here.
        **kwargs : (username = user_name, email=user_email)
    """
    db_obj = obj.query.filter_by(**kwargs).first()
    if db_obj is not None:
        return True
    else:
        return False

【讨论】:

以上是关于如何优雅地检查对象/实例/变量的存在,如果它存在于python中,同时将其分配给变量?的主要内容,如果未能解决你的问题,请参考以下文章

在类的实例化期间如何检查该类的对象是不是已经存在,如果存在,则指向已经存在的对象? [复制]

如何在读取之前测试存储中是不是存在可序列化对象?

未定义变量时如何优雅地使管道失败

Python:检查范围内是不是存在对象[重复]

如果@include 中存在变量,则检查刀片

不区分大小写地检查字符串是不是存在于数组中