Python:在while循环中使用生成器

8

以下是我目前的代码:

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v
    return False

def up_data(v):
    t = 0
    h = 0
    vel = v
    while h < 1:
        t += .0001
        h = -4.9*t**2 - v*t
        vel = -9.8*t - v
        yield h, vel, t

我想做的是让我的main()函数在其有效期内输出down_data(1)的值。运行这段不完整的代码只会设置一个无限循环,我不确定为什么。
我试图将这两个函数组合在一起以模拟弹跳球,但由于yield函数的存在,将它们拼接在一起变得困难。我尝试创建一个main()函数并在其中运行while循环,但这样会导致无限循环。以下是我尝试过的main()
def main():
    data = [] 
    while down_data(1):
        data.append(down_data(1))
    print(data)

也许有更简单的方法来做到这一点吗? 我想要的 main()函数应该是这样的:
编辑:我也尝试了这个,但是同样的问题发生了; while循环没有关闭以移动到下一个i:
def main():
    data = []
    for i in down_data(1):
        while i[0] > 0:
            data.append(i[0])
            continue
    print(data)

continue 返回到 while,而不是 for - 所以它是无用的。也许在最后一个例子中使用 if 代替 while - furas
2个回答

15

在Python中,生成器函数的使用方式与你尝试使用它们的方式略有不同。

你应该只调用down_data(1)一次。

尝试这样做:

g = 9.8

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v

for h, v in down_data(1):
    print h, v

这将生成许多输出行,但当h达到0时,它将停止。
解释:一个带有yield的Python函数在被调用时会产生一个生成器。每次你在生成器上调用next,生成器运行直到它遇到一个yield,并且产生的值返回给调用者。如果生成器在没有产生任何东西的情况下到达其主体的末尾,则会引发StopIteration异常。
当您在for语句中迭代生成器时,当生成器没有更多数据可产生时,for循环会干净地退出。

3

Ray说生成器在for e in gen之外使用可能会很棘手,因为它隐藏了StopIteration异常。

但是在Python 3.5和Spyder IDE中没有SyntaxError: 'return' with argument inside generator

g = 1

def down_data(h):
    t = 0
    while h > 0:
        t += .0001
        h = -4.9*t**2 + 1
        v = g*t
        yield h, v
    return 'fred' # this will be returned on StopIteration Exception

def mainly():
   data_gen =  down_data(1)
   data = [next(data_gen)]
   while data_gen:
       data.append(next(data_gen))
   #print(data)
   return len(data)        

主要是由于StopIteration异常导致mainly()失败,但是在异常之后down_data(h)返回确实得到执行:

 mainly()
Traceback (most recent call last):

  File "<ipython-input-103-015c95441865>", line 1, in <module>
    mainly()

  File "C:/Users/john/mypy/mySE_answers/tagd.py", line 48, in mainly
    data.append(next(data_gen))

StopIteration: fred

如果你使用自己的next()调用来遍历生成器并到达末尾,则需要显式地使用try/except语句。

def my_try():
   data_gen =  down_data(1)
   try:
       data = [next(data_gen)]
       while True:
           data.append(next(data_gen))
   except: StopIteration

   return len(data), data[-1]

my_try()
Out[104]: (4518, (-0.0002038759998519435, 0.45179999999996656))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接