Python - curious / unexpected behavior - operator precedence

I recently experimented with python generators a bit, and I came across the following curious behavior, and I'm curious to understand why this is happening and what is happening:

def generating_test(n): for a in range(n): yield "a squared is %s" % a*a # Notice instead of a**2 we have written a*a for asquare in generating_test(3): print asquare 

Output:

 a squared is 1 a squared is 2a squared is 2 

Unlike the following script, which generates the expected result:

 def generating_test(n): for a in range(n): yield "a squared is %s" % a**2 # we use the correct a**2 here for asquare in generating_test(3): print asquare 

Output:

 a squared is 0 a squared is 1 a squared is 4 
+7
source share
3 answers

This has nothing to do with generators:

 >>> a = 2 >>> "a squared is %s" % a 'a squared is 2' >>> ("a squared is %s" % a)*a 'a squared is 2a squared is 2' >>> "a squared is %s" % a*a 'a squared is 2a squared is 2' >>> "a squared is %s" % (a*a) 'a squared is 4' 

The % op operation is performed before multiplication, using the string and the first a as arguments. Your a**2 works because ** op with a and 2 as arguments is evaluated to % .

+20
source

The order of Python operations is left to right, unless PEMDAS is used. The row interpolation operator seems to have the same priority as modulation and multiplication, because if you reverse the order by doing the multiplication to the left of the interpolation, it has priority:

 >>> print 3 * "a foo %s" % 'hi' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: not enough arguments for format string >>> print 3 * "a foo %s" % ('hi', 'ho', 'yo') a foo hia foo hoa foo yo 

However, as you have shown, exponentiation is superior to order from left to right.

Update: in the same document, in the section Binary arithmetic operations , it states something denotatively obvious, but connotatively relevant:

... the% operator is also overloaded with string and unicode objects to perform string formatting (also known as interpolation).

Although it seems to just tell you what the % operator does, I think its location and context also suggests that it has the same priority, regardless of whether it is used modulo or interpolated.

+8
source

When you observe unexpected behavior, start the analysis, diverting it to the simplest possible case. A simple case will be easier to learn and understand.

Unexpected behavior:

 >>> 'hello %s' % 3 * 2 'hello 3hello 3' 

(You expected 'hello 6' )


We believe that Python should interpret the command as 'hello 3' * 2 , not 'hello %d' % 6 . We are trying to force the second interpretation with parentheses

 >>> "hello %s" % (3*2) 'hello 6' 

Eureka!

We have demonstrated that the % line format operator has greater or equal priority than multiplication. We check the Python documentation - yes, this confirms this http://docs.python.org/reference/expressions.html#summary

To confirm that priority is equal, we can try it the other way around:

 >>> "%d,"*2%(1,2) '1,2,' 

Having seen that the comma (,) is duplicated, we believe that the multiplication "%d," * 2 was performed before formatting the string % . If multiplication can precede string formatting, and string formatting precedes multiplication, they should be equal in priority.

+5
source

All Articles