Caching Values ​​in Python List Views

I use 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 is checked in the if statement so that it does not call get again on obj when it generates a returned list?

+4
source share
4 answers

If you want to stay with list / iterators, 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] 
+6
source
 resources = filter(None, (obj.get("file") for obj in iterator)) 

See the documentation for filter for your own evaluation function. Passing None for a function (as described above) filters out all values ​​that are not true.

If obj.get () returns an object that has a weird __nonzero__ method, then you need to pass lambda obj: obj != None to get the same result as the source code.

+9
source

Try something like this:

 resources = filter( lambda x: x is not None, [obj.get("file") for ob jin iterator]) 
+1
source

Create a temporary dict to store the values. Then create a function that uses this dict as a cache, and use this function in a list comprehension, for example:

 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] 

In addition, you probably already know this (and if so, please ignore this answer), but if obj.get ("file") does not make a database call, does not open the file, does not make a request over the network, or does something else potentially expensive, calling it twice per iteration, rather than once, is probably harmless, since you only add O (n) to your value.

+1
source

Source: https://habr.com/ru/post/1285981/


All Articles