[Tutor] revisiting a puzzle about -3**2 vs (-3)**2
Steven D'Aprano
steve at pearwood.info
Thu Aug 13 03:31:26 CEST 2015
On Wed, Aug 12, 2015 at 12:14:16PM -0700, D Wyatt wrote:
> >
> >>>> pow(-3, 2)
> > 9
> >
> > I'm explicitly telling Python I want the value -3 raised
> > to the power 2.
> >
> >
> > Alan G
>
> so passing any numeric expression in a function is like putting ()
> around it, correct?
Hmmm. I suppose that in a manner of speaking the answer is Yes, but I
don't think that's a helpful way of looking at things. Or at least not
accurate.
Parentheses (round brackets) are used for various tasks in Python,
including calling functions and for grouping. (There are also others.)
When you say
pow(-3, 2)
the brackets () mean "call this function". The contents of the brackets
are treated as the arguments. In this case, the parsing rules used by
the Python interpreter treat the - sign as stronger than than comma, so
that it applies - to the 3. It has nothing to do with the brackets. One
might do this as well, with no brackets involved:
my_tuple = -3, 2
which gives a tuple of two values, minus-three and two, and NOT a tuple
of (3, 2) which then has the - operator applied to it. (That would cause
an error.)
When the parser splits apart each line of code to analyse it in
preparation for executing it, it has to decide in which order each
operation applies. Often that's just left-to-right, but operators can
change that, since we want mathematical expressions to match the rules
learned in maths class, not just left-to-right evaluation.
So each operator has a priority. The higher the priority, the earlier it
applies. If you dislike that precedence, the way to tell the interpreter
to use your own priorities is to group the terms in brackets first, just
like in maths class.
Multiplication has higher priority than addition, so:
1+2*3 == 7
not 9. If you want to do the addition first, you can write:
(1+2)*3 == 9
Exponentials have higher priority still:
2*3**2 == 18
and not 36, again just like maths class. The unary + and - operators
have quite low priority, but commas are even lower. (Technically, the
comma isn't actually considered an operator, but the difference is
subtle and doesn't really matter for this discussion.)
So the differences in behaviour between:
-3**2
(-3)**2
pow(-3, 2)
etc are all to do with the order of operations, not specifically the
parens. It just happens that parentheses can be used to change the order
of operations. Let's go through each it turn:
-3**2: since exponentiation ** has highest priority, that calculates as
3**2 gives 9, then apply the - sign to get -9.
(-3)**2: since brackets *used for grouping* are highest priority, that
calculates as 3, apply the - sign to get -3, raise to the power of 2 to
get 9.
pow(-3, 2): the brackets here are used for a function call, not
grouping. The parser effectively looks inside the brackets and splits on
commas, giving two expressions: "-3" and "2". The "-3" expression is
treated as 3, apply the minus sign to get -3, and the "2" expression is
obviously just 2.
So pow() receives two arguments, -3 and 2 exactly as you would
expect, and calculates -3 squared which is 9.
To check your understanding, can you predict what this will do?
x = 2
y = -2
print(x**3, y**3, -x**3, -y**3)
(Note that this time I am using cubes, not squares.)
--
Steve
More information about the Tutor
mailing list