我在python中编写一个生成器。它的行为很奇怪,如果我将yield语句保留在原来的位置,那么函数顶部的print函数永远不会被调用。如果我删除yield函数,print语句按预期发生。目前这是代码。
def eachMovement(self):
print "Each Movement..."
if not self.isComplete():
raise ValueError("DressageScore.eachMovement: dressage score must be designated as complete.")
for i in range(0, len(self.__iMovementScores)):
yield (self.__iMovementScores[i], self.__iMovementComments[i])
删除产量可修复此问题。我在这做错了什么?为了澄清,我正在运行Python 2.7.5。请不要说服我以不同的方式做这件事,我的班级要求使用发电机。谢谢!
解: 由于我正在进行测试驱动开发,所以在编写函数的其余部分之前,我编写了raise valueerror测试。在将eachMovement完全转换为生成器之后,我的测试用例失败了,因为它没有设置为测试生成器。愚蠢的错误对我而言。这是现在完成没有问题的测试用例。感谢您的所有帮助
def test1300_910_EachMovementNotComplete(self):
myGen = self.dsRider.eachMovement()
self.assertRaises(ValueError, myGen.next)
答案 0 :(得分:4)
如果只是调用生成器函数,它将返回生成器对象,并且不会执行该函数。您需要在生成器对象上使用next
函数或在next
生成器对象上调用list
函数的其他函数。
def myGen():
print "Welcome"
for i in range(10):
yield i
print myGen()
print list(myGen())
print next(myGen())
<强>输出强>
<generator object myGen at 0x7f1548366aa0>
Welcome
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Welcome
0
通常,生成器用于迭代(因为一旦生成器耗尽,就不会使用。必须为下一次迭代创建一个新的生成器对象。)所以最好的用法就是这样
for num in myGen():
print num
<强>输出强>
Welcome
0
1
2
3
4
5
6
7
8
9
答案 1 :(得分:4)
我怀疑你只是打电话给my_obj.eachMovement()
,对吗?
与函数不同,生成器执行称为“惰性求值”的操作。基本上,Python将避免在完全需要之前运行该函数(这很有用,因为它允许您编写返回无限量元素的生成器,允许用户仅使用他们需要的内容,与普通函数相比,会扼杀类似的输入。)
您需要执行以下任一操作:
>>> my_gen = my_obj.eachMovement()
>>> print next(my_gen)
Each Movement...
0 # whatever value
...或类似的东西:
>>> for i in my_obj.eachMovement():
print i
Each Movement...
0
1
# etc
这两种方法都会强制Python实际评估生成器,因为它需要数据才能继续运行。
答案 2 :(得分:1)
yield
是lazy evaluation的样式,简而言之,序列的连续元素只在需要时执行。
例如,内置的Python(2.7)函数xrange
是一个生成器,Python是一个惰性求值器的术语。
与使用xrange
的方式相同,您需要使用以下功能:
for movement in eachMovement:
# Do stuff with movement