我在Python中有以下语句,其中ori是一个字符串
[ori[ori.rfind(' ') + 1:], ori[:ori.rfind(' ')]]
我们可以看到ori.rfind('')被调用两次,解释器是否足够聪明,只能评估一次该函数?
我们可以做到以下几点:
s = ori.rfind(' ') return [ori[s+1:], ori[:s]]
但这会使用两行。我打算在字符串列表的列表理解中使用此语句,并希望此函数是一行。
在这种情况下,解释器实际上更容易理解,因为字符串是不可变的。我的猜测也许是翻译可以很聪明,以避免重新评估。一般来说,如果对象是不可变的,解释器是否足够聪明?
答案 0 :(得分:5)
我认为你不能指望只有一次评估函数的解释器,但是这里有一个与你当前代码相当的替代方法,它比两行方法更短,效率更高:
ori.rsplit(' ', 1)[::-1]
示例和时序比较:
In [1]: ori = 'foo bar baz'
In [2]: [ori[ori.rfind(' ') + 1:], ori[:ori.rfind(' ')]]
Out[2]: ['baz', 'foo bar']
In [3]: ori.rsplit(' ', 1)[::-1]
Out[3]: ['baz', 'foo bar']
In [4]: %timeit [ori[ori.rfind(' ') + 1:], ori[:ori.rfind(' ')]]
1000000 loops, best of 3: 732 ns per loop
In [5]: %timeit ori.rsplit(' ', 1)[::-1]
1000000 loops, best of 3: 514 ns per loop
In [6]: %timeit s = ori.rfind(' '); [ori[s+1:], ori[:s]]
1000000 loops, best of 3: 490 ns per loop
答案 1 :(得分:2)
解释器可以安全地执行子表达式ori.rfind(' ')
的唯一方法是,如果它知道
rFind
之间没有任何表达导致任何突变如果其中任何一个不成立,那么缓存结果并重复使用将是不安全的。考虑到Python的动态特性,几乎不可能有这些保证,因此这样的操作无法缓存+重用