反勾对 Python 解释器意味着什么? 示例: ‘ num’

我在研究列表理解法时,在另一个网站上偶然发现了这个小片段:

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

44600 次浏览

Backticks are a deprecated alias for repr(). Don't use them any more; the syntax was removed in Python 3.0.

Using backticks seems to be faster than using repr(num) or num.__repr__() in version 2.x. I guess it's because additional dictionary lookup is required in the global namespace (for repr), or in the object's namespace (for __repr__), respectively.


Using the dis module proves my assumption:

def f1(a):
return repr(a)


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


def f3(a):
return `a`

Disassembling shows:

>>> 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 involves a global lookup for repr, f2 an attribute lookup for __repr__, whereas the backtick operator is implemented in a separate opcode. Since there is no overhead for dictionary lookup (LOAD_GLOBAL/LOAD_ATTR) nor for function calls (CALL_FUNCTION), backticks are faster.

I guess that the Python folks decided that having a separate low-level operation for repr() is not worth it, and having both repr() and backticks violates the principle

"There should be one-- and preferably only one --obvious way to do it"

so the feature was removed in Python 3.0.

My guess is that num doesn't define the method __str__(), so str() has to do a second lookup for __repr__.

The backticks look directly for __repr__. If that's true, then using repr() instead of the backticks should give you the same results.

Backtick quoting is generally non-useful and is gone in Python 3.

For what it's worth, this:

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

is marginally faster than the backtick version for me. But worrying about this is probably a premature optimisation.