我最近一直在尝试使用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
答案 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
有效,因为在**
之前评估a
以2
和%
为参数的操作。
答案 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
之前执行了乘法%
。如果乘法可以在字符串格式之前,并且字符串格式在乘法之前,则它们必须在优先级上相等。