До тех пор, пока вы вызываете fetch_output
один раз для каждого предмета, производительности не будет (очевидно, будет один, если вы дважды вызываете fetch_output
в одном и том же экземпляре SerializedContentItem
).И не делать бесполезных операций, как правило, тоже хорошо (вы не ожидаете, что open("/path/to/some/file.ext")
прочитает содержимое файла, не так ли?)
Единственное предостережение заключается в том, что с исходной версией, если item
мутирует между инициализацией SerializedContentItem
и вызовом fetch_output
, изменение не будет отражено в выводе json (так как оно создано прямо во время инициализации), в то время как в вашей "ленивой" версии эти изменения будут отражатьв JSON.Независимо от контекста это зависит от того, является ли это проблемой, потенциальной проблемой или просто тем, что вы хотите.
РЕДАКТИРОВАТЬ:
что вызвало мой вопрос:в соответствии с моим (плохим) пониманием yield, его использование здесь имеет смысл: мне нужно только итерировать элементы страницы один раз, поэтому делайте это таким образом, чтобы минимизировать использование памяти.Но основная часть работы в настоящее время не выполняется в функции yield, она выполняется в строке над ней, когда создается экземпляр класса, что делает yield немного бессмысленным.Или я неправильно понимаю, как это работает?
Боюсь, вы действительно неправильно понимаете yield
.Откладывание json-серализации до тех пор, пока yield json_item.fetch_output()
не изменит ничего (nada, zero, zilch, shunya) на потребление памяти по сравнению с оригинальной версией.
yield
это не функция, это ключевое слово.Он превращает содержащую ее функцию в «функцию генератора» - функцию, которая возвращает объект генератора (ленивый итератор), который затем можно перебрать.Это ничего не изменит в памяти, используемой для jsonify элемента, и то, происходит ли это jsonification «в той же строке», что и ключевое слово yield
, или нет, совершенно не имеет значения.
Что приносит вам генератор (по сравнению с/ Использование памяти) заключается в том, что вам не нужно создавать целый список содержимого сразу, например:
def eager():
result = []
for i in range(1000):
result.append("foo {}\n".format(i))
return result
with open("file.txt", "w") as outfile:
for item in eager():
outfile.write(item)
Этот FIRST создает список из 1000 элементов в памяти, а затем перебирает его.
vs
def lazy():
result = []
for i in range(1000):
yield "foo {}\n".format(i)
with open("file.txt", "w") as outfile:
for item in lazy():
outfile.write(item)
это лениво генерирует строку за строкой на каждой итерации, поэтому вы не получите список из 1000 элементов в памяти - НО вы по-прежнему генерируете 1000 строк, каждая изони используют то же количество места, что и в первом решении.Разница в том, что, поскольку (в этом примере) вы не сохраняете никаких ссылок на эти строки, они могут собираться мусором на каждой итерации, в то время как хранение их в списке не позволяет собирать их до тех пор, пока в самом списке больше не будет ссылок..