What does the power (**) operator mean in python?

In other words, what exists behind two stars? Is it just multiplying the number x times or something else? As a follow-up question, it is better to write 2 ** 3 or 2 * 2 * 2. I ask because I heard that in C ++ it is better not to use pow () for simple calculations, since it calls a function.

+5
source share
5 answers

If you are interested in working with internal components, I would parse the instruction to get the CPython bytecode to which it is bound. Using Python3:

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

OK, so it seems that I did the calculation correctly as I entered and saved the result. You get exactly the same CPython bytecode for 2 * 2 * 2 (feel free to try). So, for expressions that are evaluated by a constant, you get the same result, and that doesn't matter.

What if you need the power of a variable?

Now you get two different bits of bytecode:

 »»» 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 

Now, of course, the BINARY_MULTIPLY question is faster than the BINARY_POWER operation?

The best way to try is to use timeit. I will use the magic of IPython %timeit . Here is the output for multiplication:

 %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 

and for power

 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 

You might want to repeat this for typical inputs, but empirically it looks like multiplication is faster (but pay attention to the cited output variance clause).

If you need further internal functions, I would suggest delving into CPython code.

+4
source

The ** operator will internally use an iterative function (the same semantics as the built-in pow() ( Python docs ), which probably means that it simply calls this function).

Therefore, if you know the power and can hard code it, using 2*2*2 is likely to be slightly faster than 2**3 . This is slightly related to the function, but I believe that the main performance issue is that it will use a loop.


Note that it is still pretty silly to replace more readable code for less readable code when it is as simple as 2**3 , at best the performance gain is minimal.

0
source

While the second is slightly faster for numbers, the advantage is very low compared to the first: readability . If you are going for a while and you are being pressured to do such an optimization, then python is probably not the language you should use .

Note: except numbers:

a ** b translates to

 a.__pow__(b) 

whereas a * a * a is a challenge

 a.__mul__(a.__mul__(a)) 

Test code:

 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 

For my car:

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

If you ask frankly, multiplication is a little faster.

 >>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 

But speed is not the only thing to consider when you choose one of two options. From the example, what is easier when calculating 2 power of 20? Just write 2**20 or use for a loop that will repeat 20 times and perform some multiplication task?

0
source

From the docs :

The power operator associates more strongly than the unary operators on the left; it binds less tightly than the unary operators on the right. Syntax:

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

Thus, in an incomparable sequence of power and unary operators, operators are evaluated from right to left (this does not limit the evaluation order for operands): -1**2 leads to -1 .

A power operator has the same semantics as the pow() built-in function when called with two arguments: it gives a left argument raised to the extent of its correct argument.

This means that in Python: 2**2**3 evaluates to 2**(2**3) = 2**8 = 256 .

In mathematics, folded exponents are applied top to bottom. If it weren’t done like this, you would just get multiplication of indicators:

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

It can be a little faster, just make the multiplication, but much less readable.

-1
source

Source: https://habr.com/ru/post/1236169/


All Articles