我正在玩列表理解,我在另一个网站上偶然发现了这个小片段:
return ''.join([`num` for num in xrange(loop_count)])
我花了几分钟尝试复制这个函数(通过键入),然后才意识到`num`
位正在破坏它。
用这些字符将语句括起来有什么作用?在我看来,它等同于str(num)。但是当我计时的时候:
return ''.join([str(num) for num in xrange(10000000)])
它需要4.09s,而:
return ''.join([`num` for num in xrange(10000000)])
需要2.43秒。
两种方法的结果相同,但其中一种方法的速度慢得多。这里发生什么事情?
编辑:奇怪的...与`num`
相比,repr()
给出的结果稍慢一些。2.99s vs 2.43s。使用Python 2.6 (还没有尝试3.0 )。
发布于 2009-11-04 19:03:59
Backticks是repr()
的一个弃用别名。不再使用它们,在Python3.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()
和反引号也违背了这个原则
“应该有1个,最好只有一个--显而易见的方法”
因此,Python3.0中删除了该功能。
发布于 2009-11-04 19:32:57
反引号通常是没有用的,在Python3中也没有了。
值得一提的是,这是:
''.join(map(repr, xrange(10000000)))
对我来说,它比反引号版本稍微快一点。但担心这一点可能是一个过早的优化。
发布于 2009-11-04 19:05:23
我的猜测是num
没有定义__str__()
方法,因此str()
必须对__repr__
进行第二次查找。
反引号直接查找__repr__
。如果这是真的,那么使用repr()
而不是反标记应该会得到相同的结果。
https://stackoverflow.com/questions/1673071
复制相似问题