Кэширование значений в списках Python - PullRequest
5 голосов
/ 09 июня 2009

Я использую следующее понимание списка:

resources = [obj.get("file") for obj in iterator if obj.get("file") != None]

Есть ли способ "кэшировать" значение obj.get("file"), когда оно проверено в операторе if, чтобы ему не приходилось снова вызывать get для obj при генерации списка возврата?

Ответы [ 4 ]

9 голосов
/ 09 июня 2009
resources = filter(None, (obj.get("file") for obj in iterator))

См. Документацию для фильтра , чтобы узнать, как обеспечить собственную функцию оценки. Передача None для функции (как указано выше) отфильтровывает все значения, которые не соответствуют действительности.

Если obj.get () возвращает объект со странным методом __nonzero__, вам нужно будет передать lambda obj: obj != None, чтобы получить точно такой же результат, как и ваш исходный код.

6 голосов
/ 10 июня 2009

Если вы хотите остаться со списком / итератором вместо использования filter, вы можете просто использовать:

resources = [file_obj
             for file_obj in (obj.get("file") for obj in iterator)
             if file_obj is not None]
1 голос
/ 09 июня 2009

Создать временный диктат для хранения значений. Затем создайте функцию, которая использует этот 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 ("файл") не выполняет вызов базы данных, открывает файл, делает запрос по сети или выполняет что-то еще потенциально дорогое, вызывать его дважды за итерацию, а не один раз, вероятно, безвредно, поскольку вы только добавляете O (n) к своей стоимости.

1 голос
/ 09 июня 2009

Попробуйте что-то вроде этого:

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