如何将dict(zip(range(n),range(n)))翻译成Python 3?

时间:2018-06-08 19:47:01

标签: python python-3.x python-2.7

我刚刚在代码上运行了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)))))

dictzip都可以使用迭代器,为什么会这样翻译?

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正确的工具(我们需要在转换~150KLOC的python时运行2和3)

更新:我在表格中添加了dict(itertools.izip(xrange(n), xrange(n)))作为算法C.

1 个答案:

答案 0 :(得分:4)

py2to3没有看到全局图片。它只是创建了一些等效代码,通过添加list包装来替换现在不再创建列表的函数,以确保:

  • 可以下标结果
  • 可以根据需要多次迭代结果

(它还将括号放在print附近,......但这里不相关)

因此它会尝试让您的代码运行,但无法保证性能,例如

在您的示例中,列表包装器没用,因为dict使用了迭代器。

因此,此工具对于使代码快速运行非常有用,但如果不与原始代码进行比较并决定要保留哪些代码或要更改的内容,则不应使用此工具。

该工具可能会改进为:

  • 避免在循环中使用迭代器时换行
  • 当迭代器传递给一个以迭代为输入的对象时,避免包装。

在你的情况下

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 3x不兼容,2to3不能轻易修复,但它错过了很多的案例,好吧,它总比没有好,例如它找到了臭名昭着的has_key电话)
  • 使用py2to3结果与原始代码进行比较,手动决定应用更改的位置
  • 你也可以使用像GrepWin这样的工具进行多搜索/替换来做py2to3会做的事情,只是降低性能的风险较小:
    • 搜索iteritems,替换为items
    • 搜索xrange,替换为range
    • 追踪dict.has_key来电,unicode内置
    • 我可能会忘记一些......
  • 使用python 3广泛地测试和公开你的代码。有些东西对于工具和-3选项是不可见的,就像你使用二进制模式读取文本文件一样