问题
I'm using the following list comprehension:
resources = [obj.get("file") for obj in iterator if obj.get("file") != None]
Is there a way to "cache" the value of obj.get("file")
when it's checked in the if statement so that it doesn't have to call get
again on obj when it generates the return list?
回答1:
If you want to stay with list / iterator comprehensions instead of using filter
you can simply use:
resources = [file_obj
for file_obj in (obj.get("file") for obj in iterator)
if file_obj is not None]
回答2:
resources = filter(None, (obj.get("file") for obj in iterator))
See the documentation for filter for how to provide your own evaluation function. Passing None
for the function (as above) filters out all values which aren't true.
If obj.get() returns an object which has a weird __nonzero__
method then you'd need to pass lambda obj: obj != None
to get exactly the same result as your original code.
回答3:
Try something like this:
resources = filter( lambda x: x is not None, [obj.get("file") for ob jin iterator])
回答4:
Create a temporary dict to hold values. Then, create a function that uses this dict as a cache, and use that function in the list comprehension, like so:
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]
Also, you probably already know this (and if so, please disregard this answer), but unless obj.get("file") is making a database call, opening a file, making a request over a network, or doing something else potentially expensive, calling it twice per iteration instead of once is probably harmless, since you're only adding O(n) to your cost.
回答5:
Starting from Python 3.8 one can use an assignment expression to avoid calling the function twice:
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']
来源:https://stackoverflow.com/questions/971857/caching-values-in-python-list-comprehensions