92

我正在玩列表推导,我在另一个网站上遇到了这个小片段:

return ''.join([`num` for num in xrange(loop_count)])

我花了几分钟尝试复制该功能(通过键入),然后才意识到该`num`位正在破坏它。

在这些字符中包含一个语句有什么作用?据我所知,它相当于str(num)。但是当我计时时:

return ''.join([str(num) for num in xrange(10000000)])

它需要 4.09 秒,而:

return ''.join([`num` for num in xrange(10000000)])

耗时 2.43 秒。

两者都给出相同的结果,但一个要慢得多。这里发生了什么?

编辑:奇怪...repr()给出的结果比`num`. 2.99 秒与 2.43 秒。使用 Python 2.6(尚未尝试 3.0)。

4

3 回答 3

128

反引号是不推荐使用的别名repr()。不要再使用它们了,Python 3.0 中删除了语法。

使用反引号似乎比在 2.x 版中使用repr(num)或更快。我猜这是因为分别在全局命名空间(for )或对象的命名空间(for )num.__repr__()中需要额外的字典查找。repr__repr__


使用该dis模块证明了我的假设:

def f1(a):
    return repr(a)

def f2(a):
    return a.__repr__()

def f3(a):
    return `a`

拆机显示:

>>> import dis
>>> dis.dis(f1)
  3           0 LOAD_GLOBAL              0 (repr)
              3 LOAD_FAST                0 (a)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE
>>> dis.dis(f2)
  6           0 LOAD_FAST                0 (a)
              3 LOAD_ATTR                0 (__repr__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE        
>>> dis.dis(f3)
  9           0 LOAD_FAST                0 (a)
              3 UNARY_CONVERT       
              4 RETURN_VALUE   

f1涉及对 的全局查找reprf2对 的属性查找__repr__,而反引号运算符在单独的操作码中实现。由于字典查找 ( LOAD_GLOBAL/ LOAD_ATTR) 和函数调用 ( CALL_FUNCTION) 都没有开销,因此反引号更快。

我猜 Python 的人认为有一个单独的低级操作 forrepr()是不值得的,并且同时使用repr()和反引号违反了原则

“应该有一种——最好只有一种——明显的方式来做到这一点”

所以这个特性在 Python 3.0 中被移除了。

于 2009-11-04T11:03:58.820 回答
10

反引号通常没有用,并且在 Python 3 中消失了。

对于它的价值,这是:

''.join(map(repr, xrange(10000000)))

对我来说比反引号版本快一点。但担心这一点可能是过早的优化。

于 2009-11-04T11:32:57.210 回答
1

我的猜测是它num没有定义方法__str__(),所以str()必须对__repr__.

反引号直接查找__repr__。如果这是真的,那么使用repr()而不是反引号应该会给你相同的结果。

于 2009-11-04T11:05:22.923 回答