python中的幂运算符(**)转化为什么?

时间:2015-11-17 16:50:56

标签: python operators translate

换句话说,两个星号背后是什么?它只是将数字乘以x倍或其他?作为后续问题,写2 ** 3或2 * 2 * 2是否更好。我问,因为我听说在C ++中最好不要使用pow()进行简单的计算,因为它调用了一个函数。

5 个答案:

答案 0 :(得分:6)

如果您对内部感兴趣,我会反汇编指令以获取它映射到的CPython字节码。使用Python3:

»»» def test():
    return 2**3
   ...: 
»»» dis.dis(test)
  2           0 LOAD_CONST               3 (8)
              3 RETURN_VALUE

好的,所以在进入时似乎已经完成了计算,并存储了结果。您获得2 * 2 * 2的完全相同的CPython字节码(随意尝试)。因此,对于求值为常量的表达式,您得到相同的结果,并不重要。

如果你想要一个变量的力量怎么办?

现在你得到两个不同的字节码:

»»» def test(n):
        return n ** 3

»»» dis.dis(test)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (3)
              6 BINARY_POWER
              7 RETURN_VALUE

VS

»»» def test(n):
    return n * 2 * 2
   ....: 

»»» dis.dis(test)
  2           0 LOAD_FAST                0 (n)
              3 LOAD_CONST               1 (2)
              6 BINARY_MULTIPLY
              7 LOAD_CONST               1 (2)
             10 BINARY_MULTIPLY
             11 RETURN_VALUE

现在的问题当然是BINARY_MULTIPLY比BINARY_POWER操作更快吗?

尝试这种方法的最佳方法是使用timeit。我将使用IPython %timeit魔法。这是乘法的输出:

%timeit test(100)
The slowest run took 15.52 times longer than the fastest. This could mean that an intermediate result is being cached 
10000000 loops, best of 3: 163 ns per loop

和权力

The slowest run took 5.44 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 473 ns per loop

您可能希望对代表性输入重复此操作,但从经验上看,乘法似乎更快(但请注意提到的输出方差的提示)。

如果你想进一步的内部,我建议深入研究CPython代码。

答案 1 :(得分:1)

虽然第二个数字对于数字来说稍微快一点,但与第一个相比,优势非常低:可读性。如果你想要时间,并且你被迫做出这样的优化,那么python可能不是你应该使用的语言

注意:除了数字之外:

a ** b 转换为

a.__pow__(b) 

a * a * a 是对

的调用
a.__mul__(a.__mul__(a))

测试代码:

import time

s = time.time()
for x in xrange(1,1000000):
    x**5
print "done in ", time.time() - s

s = time.time()
for x in xrange(1,1000000):
    x*x*x*x*x
print "done in ", time.time() - s

我的机器产量:

done in  0.975429058075
done in  0.260419845581
[Finished in 1.2s]

答案 2 :(得分:0)

**运算符将在内部使用迭代函数(与内置pow()Python docs)相同的语义,这可能意味着它只是调用该函数)。 / p>

因此,如果您知道电源并且可以对其进行硬编码,那么使用2*2*2可能会比2**3快一点。这与该功能有点关系,但我认为主要的性能问题是它将使用循环。

请注意,如果只有2**3那么简单的代码来替换代码较不易读的代码,那么它仍然非常愚蠢,性能增益最小。

答案 3 :(得分:0)

来自the docs

  

权力运算符比左边的一元运算符绑定得更紧密;它比右边的一元运算符更紧密。语法是:

power ::=  primary ["**" u_expr]
  

因此,在功率和一元运算符的未加密集的序列中,运算符从右到左进行求值(这不会限制操作数的求值顺序):-1**2得到-1。< / p>      

当使用两个参数调用时,幂运算符与内置pow()函数具有相同的语义:它将其左参数提升为其右参数的幂。

这意味着,在Python中:2**2**3被评估为2**(2**3) = 2**8 = 256

在数学中,堆叠指数从上到下应用。如果没有这样做,你只会得到指数的乘法:

(((2**3)**4)**5) = 2**(3*4*5)

进行乘法可能要快一点,但可读性要差一些。

答案 4 :(得分:0)

如果你坦率地问,乘法会快一点。

>>timeit.timeit('[i*i*i*i for i in range(100)]', number=10000)
0.262529843304
>>timeit.timeit('[i**4 for i in range(100)]', number=10000)
0.31143438383

但是,当您从两个选项中选择一个时,速度并不是唯一要考虑的因素。例如,计算2到电源20时更容易?只需编写2**20或使用for循环,它将迭代20次并执行一些乘法任务?