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

Dom*_*mra 81 python list-comprehension

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

return ''.join([`num` for num in xrange(loop_count)])
Run Code Online (Sandbox Code Playgroud)

我花了几分钟试图复制这个函数(通过输入),然后才意识到`num`它正在破坏它.

在这些字符中包含语句的内容是什么?从我所看到的它相当于str(num).但是当我计时:

return ''.join([str(num) for num in xrange(10000000)])
Run Code Online (Sandbox Code Playgroud)

它需要4.09s而:

return ''.join([`num` for num in xrange(10000000)])
Run Code Online (Sandbox Code Playgroud)

需要2.43秒.

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

编辑:奇怪... repr()给出稍微慢一点的结果`num`.2.99s vs 2.43s.使用Python 2.6(尚未尝试过3.0).

Fer*_*yer 118

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

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


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

def f1(a):
    return repr(a)

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

def f3(a):
    return `a`
Run Code Online (Sandbox Code Playgroud)

拆卸显示:

>>> 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   
Run Code Online (Sandbox Code Playgroud)

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

我想Python人们认为单独进行低级操作repr()是不值得的,并且使用repr()和反对都违反了原则

"应该有一个 - 最好只有一个 - 明显的做法"

所以在Python 3.0中删除了该功能.

  • 反引号被弃用的原因也是因为`字符本身; 它很难打字(在某些键盘上),很难看出它是什么,很难在Python书籍中正确打印.等等. (8认同)
  • @ kaizer.se:谢谢你指出这一点.这可能是删除反引号的主要原因,请参阅邮件列表档案中的Guidos声明:http://mail.python.org/pipermail/python-ideas/2007-January/000054.html (4认同)
  • 使用repr()而不是反引号.反引号是repr()的折旧语法来3.0.我实际上更喜欢反叛的外观,而不是调用另一个函数. (2认同)

bob*_*nce 9

反引用引用通常是无用的,并且在Python 3中使用.

对于它的价值,这个:

''.join(map(repr, xrange(10000000)))
Run Code Online (Sandbox Code Playgroud)

比我的反引号版本略快.但担心这可能是一个不成熟的优化.

  • bobince的结果对我来说并不奇怪.根据经验,Python中的隐式循环比显式循环更快,通常更快.`map`在C中实现,使用C循环,比在虚拟机中执行的Python循环快得多. (6认同)
  • 也不奇怪,这对于列表理解的声誉来说太糟糕了(在这个例子中命中率达到了30%).但我宁愿明确而不是速度快的代码,除非这非常重要,所以这里没什么大不了的.话虽这么说,map()函数不会让我觉得不清楚,LC有时会被高估. (6认同)
  • `map`看起来非常简洁明了,我甚至都不懂Python. (4认同)
  • 实际上,`timeit`会产生更快的结果`''.join(map(repr,xrange(0,1000000)))`而不是'''.join([repr(i)for i in xrange(0,1000000) ])`(更糟糕的是'''.join((在xrange(0,1000000)中我对i的repr(i)))).这有点令人失望;-) (3认同)
  • 为什么要向后退一步并使用map而不是list/iterator comprehensions? (2认同)