反引号对python解释器意味着什么:`num`


87

我正在玩列表理解,并且在另一个站点上遇到了这个小片段:

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)。


8
阅读skymind.com/~ocrow/python_string上的“另一个站点”后,我遇到了类似的问题,并找到了此页面。好的问题和好的答案:)
netvope

Answers:


122

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

使用反引号似乎比使用2.x版repr(num)或更快num.__repr__()。我猜这是因为分别需要在全局名称空间(for repr)或对象的名称空间(for __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专家认为repr()不值得为此使用单独的低级操作,并且同时使用repr()反引号会违反该原理

“应该有一种-最好只有一种-显而易见的方法”

因此该功能已在Python 3.0中删除。


我想找到如何用某些函数调用来替换反引号,但是似乎不可能,或者是吗?
吉里(Jiri)2009年

2
使用repr()代替反引号。反引号是repr()3.0的折旧语法。实际上,我更喜欢反引号的外观,而不是调用ANOTHER函数。
多米尼克·布·萨姆拉

8
不推荐使用反引号的原因还在于字符本身。可能很难打字(在某些键盘上),很难看清它的意思,很难在Python书籍中正确打印。等等
u0b34a0f6ae

4
@ kaizer.se:感谢您指出这一点。这可能是删除反引号的主要原因,请参阅邮件列表档案中的Guidos声明:mail.python.org/pipermail/python-ideas/2007-January/000054.html
Ferdinand Beyer

最初发布的问题是因为我实际上无法在键盘上找到反引号;)在波浪线下方,经过谷歌搜索后看起来很像。
Dominic Bou-Samra,2009年

10

反引号通常是无用的,并且在Python 3中已经消失了。

对于它的价值,这是:

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

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


2
为什么要退一步并使用map而不是list / iterator理解?
nikow,

4
实际上,timeit产生''.join(map(repr, xrange(0, 1000000)))比更快的结果''.join([repr(i) for i in xrange(0, 1000000)])(甚至更差''.join( (repr(i) for i in xrange(0, 1000000)) ))。有点令人失望;-)
RedGlyph

8
bobince的结果对我来说并不奇怪。根据经验,Python中的隐式循环比显式的要快,通常快得多。map使用C循环在C中实现,它比在虚拟机中执行的Python循环快得多。
Ferdinand Beyer

7
也不感到惊讶,这对于列表理解的声誉实在是太糟糕了(在此示例中命中率为30%)。但是我宁愿使用清晰的代码,也不愿编写速度极快的代码,除非这真的很重要,所以这里没什么大不了的。话虽如此,map()函数并没有让我感到不清楚,LC有时被高估了。
RedGlyph

4
map对我来说似乎非常清晰明了,我什至都不了解Python。
Zenexer

1

我的猜测是 num没有定义方法__str__(),因此str()必须对进行第二次查找__repr__

反引号直接寻找__repr__。如果是这样,那么使用repr()而不是使用反引号应该可以为您提供相同的结果。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.