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