Сохранение памяти Py3k путем возврата итераторов, а не списков

StackOverflow https://stackoverflow.com/questions/701088

Вопрос

Многие методы, которые раньше возвращали списки в Python 2.x, теперь, похоже, возвращают итераторы в Py3k

Являются ли итераторы также выражениями генератора?Ленивая оценка?

Таким образом, при этом объем памяти python резко сократится.Не так ли?

Как насчет программ, преобразованных из 2to3 с использованием встроенного скрипта?

Преобразует ли встроенный инструмент явно все возвращаемые итераторы в списки для обеспечения совместимости?Если это так, то преимущество Py3k в уменьшении объема памяти на самом деле не очевидно в преобразованных программах.Так ли это?

Это было полезно?

Решение

Многие из них являются не совсем итераторами, а объектами специального представления.Например, range() теперь возвращает что-то похожее на старый объект xrange - он все еще может быть проиндексирован, но лениво создает целые числа по мере необходимости.

Аналогично dict.keys() предоставляет объект dict_keys, реализующий представление в dict, вместо создания нового списка с копией ключей.

То, как это влияет на объем памяти, вероятно, зависит от программы.Конечно, больше внимания уделяется использованию итераторов, если только вам действительно не нужны списки, тогда как использование списков обычно использовалось по умолчанию в python2.Это приведет к тому, что среднестатистическая программа, вероятно, будет более эффективно использовать память.Однако случаи, когда достигается действительно большая экономия, вероятно, уже будут реализованы в виде итераторов в программах python2, поскольку действительно большое использование памяти будет выделяться и, скорее всего, уже будет рассмотрено.(например.файловый итератор уже намного эффективнее использует память, чем более старый file.readlines() способ)

Преобразование выполняется инструментом 2to3 и обычно преобразует такие вещи, как range(), в итераторы, где он может безопасно определить, что реальный список не нужен, поэтому код типа:

for x in range(10): print x

переключится на новый объект range(), больше не создавая список, и, таким образом, получит меньшее преимущество в памяти, но код, подобный:

x = range(20)

будет преобразован как:

x = list(range(20))

поскольку конвертер не может знать, ожидает ли код реальный перечислите объект в x.

Другие советы

Являются ли итераторы также выражениями генератора?Ленивая оценка?

Итератор - это просто объект со следующим методом.Что в документации чаще всего подразумевается, когда говорится, что функция возвращает итератор, так это то, что ее результат загружается лениво.

Таким образом, при этом объем памяти python резко сократится.Не так ли?

Это зависит от обстоятельств.Я бы предположил, что среднестатистическая программа не заметила бы Огромный однако разница есть.Преимущества итераторов в производительности по сравнению со списками действительно значительны только в том случае, если у вас большой набор данных.Возможно, вы захотите увидеть этот вопрос.

Одно из самых больших преимуществ итераторов перед списками - это не память, а фактически время вычислений.Например, в Python 2:

for i in range(1000000):  # spend a bunch of time making a big list
    if i == 0:
        break  # Building the list was a waste since we only looped once

Теперь возьмем, к примеру,:

for i in xrange(1000000):  # starts loop almost immediately
    if i == 0:
        break  # we did't waste time even if we break early

Хотя пример является надуманным, вариант использования не является:петли часто обрываются на полпути.Создание целого списка для использования только его части - пустая трата времени, если только вы не собираетесь использовать его более одного раза.Если это так, вы можете явно создать список: r = list(range(100)).Вот почему итераторы используются по умолчанию в большем количестве мест в Python 3;вы ничего не теряете, поскольку по-прежнему можете явно создавать списки (или другие контейнеры), когда вам нужно.Но вы не вынуждены к этому, когда все, что вы планируете сделать, это выполнить итерацию по итерируемому объекту один раз (что, я бы сказал, является гораздо более распространенным случаем).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top