Python - 好奇/意外行为 - 运算符的优先级

时间:2012-08-07 14:10:12

标签: python operator-precedence

我最近一直在尝试使用python生成器,我遇到了以下奇怪的行为,我很想知道为什么会发生这种情况以及发生了什么:

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 

输出:

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

以下脚本生成预期输出:

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 

输出:

a squared is 0
a squared is 1
a squared is 4

3 个答案:

答案 0 :(得分:20)

这与发电机没有任何关系:

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

% op在乘法之前执行,使用字符串和第一个a作为参数。您的a**2有效,因为在**之前评估a2%为参数的操作。

答案 1 :(得分:8)

Python's order of operations是从左到右,除非PEMDAS适用。字符串插值运算符显然具有与模数和乘法相同的优先级,因为如果颠倒顺序,使插值的左侧乘法,则优先:

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

但是,正如您所证明的,取幂取决于从左到右的顺序。

更新:在那个same document under Binary Arithmetic Operations中,它表明了一些显而易见的东西,但具有内涵相关性:

  

...%运算符也被字符串和unicode对象重载   执行字符串格式化(也称为插值)。

虽然这似乎只是告诉你%运算符做了什么,但我认为它的位置和上下文也告诉你它是否具有相同的优先级,无论它是否用作 modulo 插入

答案 2 :(得分:5)

当您发现意外行为时,请通过将其分解为最简单的情况来开始分析。一个简单的案例将更容易学习和理解。

出乎意料的行为:

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

(您期望'hello 6'


我们认为Python必须将命令解释为'hello 3' * 2而不是'hello %d' % 6。我们尝试用括号

强制进行第二次解释
>>> "hello %s" % (3*2)
'hello 6'

尤里卡!

我们已经证明字符串格式化运算符%的优先级大于或等于乘法。我们检查Python文档 - 是的,它确认了这个http://docs.python.org/reference/expressions.html#summary

要确认优先级相同,我们可以反过来尝试:

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

看到逗号(,)重复,我们推断在字符串格式"%d," * 2之前执行了乘法%。如果乘法可以在字符串格式之前,并且字符串格式在乘法之前,则它们必须在优先级上相等。