我正在玩列表理解,并且在另一个站点上遇到了这个小片段:
return ''.join([`num` for num in xrange(loop_count)])
我花了几分钟尝试复制功能(通过键入),然后才意识到num它被破坏了。
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)。
repr()
反引号是不推荐使用的别名repr()。不再使用它们,该语法已在Python 3.0中删除。
使用反引号似乎快于使用repr(num)或num.__repr__()在版本2.x中 我猜这是因为分别需要在全局名称空间(for repr)或对象的名称空间(for __repr__)中进行额外的字典查找。
repr(num)
num.__repr__()
repr
__repr__
使用该dis模块证明了我的假设:
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)的开销,因此反引号会更快。
f1
f2
LOAD_GLOBAL
LOAD_ATTR
CALL_FUNCTION
我猜想,Python专家认为repr()不值得为此单独进行一个低级操作,并且同时使用repr()反引号会违反该原理
“应该有一种-最好只有一种-显而易见的方法”
因此该功能已在Python 3.0中删除。