如何将 dict(zip(range(n), range(n))) 转换为 Python 3?

4

我刚对类似这样的代码(A)运行了2to3:

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微秒到4.34微秒(增加50%)。

问题.. (i) 我是否有理由不使用Python 3中的原始代码?(它产生了正确的结果,并且在我看来似乎合理);(ii) 2to3是正确的工具吗?(我们需要在转换约150KLOC的Python时同时运行在2和3上)

更新: 我已将dict(itertools.izip(xrange(n), xrange(n)))添加为表格中的算法C。


1
https://docs.python.org/2/library/2to3.html#2to3fixer-xrange - Jasper
字典字面量更快。 - Josh Lee
@Jasper 我不认为这是重复的。另一个问题是关于在for循环上下文中将列表构造函数添加到dict.keys()调用中。推理可能相似,但并不相同。另一个问题也纯粹是关于代码而不是工具的。 - thebjorn
@JoshLee 最好是这样,因为其中一个范围调用是不必要的。 - thebjorn
1个回答

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 3.x不兼容性问题,但它错过了很多情况,但总比没有好,例如它可以找到臭名昭著的has_key调用)
  • 使用py2to3并将结果与原始代码进行比较手动决定何时应用更改。
  • 您还可以使用类似GrepWin的工具进行多重搜索/替换,以执行py2to3所做的操作,只是风险较小:
    • 搜索iteritems,替换为items
    • 搜索xrange,替换为range
    • 跟踪dict.has_key调用,内置unicode
    • 我可能忘记了一些...
  • 广泛测试和暴露你的代码,使用Python 3。有些问题对工具和-3选项是不可见的,例如当你使用二进制模式读取文本文件时等。

有更好的工具吗? - thebjorn
@thebjorn 这个工具很好,错误最初是在Python2中使用了range而不是xrange,我相信。 - Olivier Melançon
@OlivierMelançon 在 Py2 中,对于小列表而言,range()xrange() 更快(至少曾经是这样)。 - thebjorn
1
@thebjorn 没有任何工具能够猜测到这里的 n 预计是很小的。 - Olivier Melançon
1
不客气。我已经移植了超过1万行代码(目前可以在Python 2.7和3.5上运行),这并不难做到。 - Jean-François Fabre
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接