我正在玩列表推导,我在另一个网站上看到了这个小片段:
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.99s vs 2.43s。使用Python 2.6(尚未尝试过3.0)。
答案 0 :(得分:113)
反引号是repr()
的弃用别名。不要再使用它们了,在Python 3.0中删除了语法。
使用反引号似乎比在版本2.x中使用repr(num)
或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
涉及repr
的全局查找,f2
__repr__
的属性查找,而反引号运算符则在单独的操作码中实现。由于字典查找(LOAD_GLOBAL
/ LOAD_ATTR
)和函数调用(CALL_FUNCTION
)没有开销,因此反引号更快。
我想Python人员认为对repr()
进行单独的低级操作是不值得的,并且repr()
和反引号都违反了原则
“应该有一个 - 最好只有一个 - 显而易见的方式”
因此在Python 3.0中删除了该功能。
答案 1 :(得分:9)
反引号引用通常是无用的,并且已经在Python 3中使用了。
对于它的价值,这个:
''.join(map(repr, xrange(10000000)))
对于我来说,比反引号版本略快。但担心这可能是一个不成熟的优化。
答案 2 :(得分:1)
我的猜测是num
没有定义方法__str__()
,因此str()
必须对__repr__
进行第二次查找。
反引号直接查找__repr__
。如果这是真的,那么使用repr()
代替反引号应该会给你相同的结果。