我正在使用以下列表理解:
resources = [obj.get("file") for obj in iterator if obj.get("file") != None]
有没有办法在if语句中检查obj.get("file")
时“缓存”它,以便在生成返回列表时不必再在obj上调用get
?
答案 0 :(得分:9)
resources = filter(None, (obj.get("file") for obj in iterator))
请参阅filter的文档,了解如何提供自己的评估功能。为函数传递None
(如上所述)会过滤掉所有不正确的值。
如果obj.get()返回一个具有奇怪__nonzero__
方法的对象,那么您需要传递lambda obj: obj != None
以获得与原始代码完全相同的结果。
答案 1 :(得分:6)
如果你想继续使用列表/迭代器理解而不是使用filter
,你可以简单地使用:
resources = [file_obj
for file_obj in (obj.get("file") for obj in iterator)
if file_obj is not None]
答案 2 :(得分:1)
尝试这样的事情:
resources = filter( lambda x: x is not None, [obj.get("file") for ob jin iterator])
答案 3 :(得分:1)
创建一个临时字典以保存值。然后,创建一个使用此dict作为缓存的函数,并在列表推导中使用该函数,如下所示:
obj_cache = {}
def cache_get (target, key):
if (target, key) not in obj_cache: obj_cache[(target, key)] = target.get(key)
return obj_cache[(target, key)]
resources = [cache_get(obj, "file") for obj in iterator if cache_get(obj, "file") != None]
另外,您可能已经知道这一点(如果是这样,请忽略此答案),但除非obj.get(“file”)正在进行数据库调用,打开文件,通过网络发出请求或执行操作其他可能很昂贵的东西,每次迭代而不是一次调用它可能是无害的,因为你只是在你的成本中加入O(n)。
答案 4 :(得分:0)
从Python 3.8开始,可以使用assignment expression避免两次调用该函数:
iterator = [{'file': 'abc'},
{'file': None},
{'file': 'def'},
{'file': None}]
res = [file for obj in iterator
if (file := obj.get("file")) is not None]
print(res)
# ['abc', 'def']