Как перевести dict (zip (range (n), range (n))) в Python 3? - PullRequest
0 голосов
/ 08 июня 2018

Я только что запустил 2to3 для кода, который выглядит следующим образом (A):

def idict(n):
    return dict(zip(range(n), range(n)))

, и он сгенерировал это (B):

def idict(n):
    return dict(list(zip(list(range(n)), list(range(n)))))

и dict и zip может потреблять итераторы, так почему этот перевод?

B тоже очень медленный.Тестирование с

python -m timeit -s "import B as t" "t.idict(10)"

со следующими результатами:

________________A______B______C___  
Python 2.7.13   2.89   3.82   2.29
Python 3.5.1    2.63   4.34   A

т.е.с 2.89 usec до 4.34 (+ 50%) с переводом по умолчанию.

Вопросы ... (i) есть ли причина, по которой я не должен использовать оригинальный код в Python 3?(он дает правильный результат и кажется мне разумным);(ii) является 2to3 правильным инструментом (нам нужно работать на 2 и 3 при переходе ~ 150KLOC питона)

Обновление: Я добавил dict(itertools.izip(xrange(n), xrange(n))) как алгоритм C встол.

1 Ответ

0 голосов
/ 08 июня 2018

py2to3 не видит общую картину.Он просто создает некоторый эквивалентный код, заменяя функции, которые больше не создают списки, добавляя list упаковщик, чтобы убедиться, что:

  • можно добавить результат
  • можно повторять результат столько раз, сколько нужно

(здесь также ставятся круглые скобки вокруг print, ... но здесь это не актуально)

Поэтому он пытается сделатьваш код запускается, но производительность не гарантируется, как на всех .

В вашем примере оболочка списка бесполезна, поскольку dict использует итератор.

Таким образом, этот инструмент полезен для быстрой работы кода, но его не следует использовать без сравнения с исходным кодом и определения того, что оставить / что изменить.

Инструмент, вероятно, можно улучшить до:

  • избегать переноса, когда итератор используется в цикле
  • избегать переноса, когда итератор передается объекту, который принимает итерацию в качестве ввода.

Inтвой случай

dict(zip(range(n), range(n)))

идеаленВсе хорошо и работает быстрее в Python 3, чем в Python 2, потому что он избегает создания промежуточного списка, поэтому оставьте это так.

эквивалент Python 2, который будет немного более сложным:

dict(itertools.izip(xrange(n), xrange(n)))

Мой совет, если у вас есть много кода для перевода (я был там):

  • используйте python -3 переключатель с интерпретатором Python 2, чтобы представить ваш код и получить некоторые предупреждения вместо того, чтобы иметьон падает в Python 3 (ну, он должен предупредить о несовместимости Python 3.x, которую 2to3 не может исправить тривиально, но он пропускает много случаев, ну, это лучше, чем ничего, например, он находитпечально известные has_key звонки)
  • использовать py2to3 и сравнить результаты с вашим исходным кодом, решить вручную , где применить изменения
  • вы также можете использовать множественный поиск / замену с такими инструментами, как GrepWin, чтобы делать то, что будет делать py2to3, только с меньшими рисками снижения производительности:
    • поиск iteritems, замена на items
    • поиск xrange, замена на range
    • отслеживание dict.has_key вызовов, unicode встроенный
    • Я могу забыть некоторые ...
  • тестирование и предоставление вашего кода с помощью python 3. некоторые вещи невидимы для инструмента и опции -3, например, когда вы используете двоичный режим для чтения текстовых файлов и тому подобное.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...