【问题标题】:Don't know why I am getting StopIteration error不知道为什么我收到 StopIteration 错误
【发布时间】:2017-11-23 16:12:37
【问题描述】:

我正在编写一个从文件接收输入的程序,每一行可能包含“ATG”或“GTG”,我很确定我已经完成了我想做的所有事情。这是我第一次在 python 中使用生成器,在研究了这个问题之后,我仍然不知道为什么我会停止迭代。为此,我的生成器必须生成一个元组,其中包含在每个字符串中找到的 ATG 或 GTG 的起始位置。

import sys

import p3mod


gen = p3mod.find_start_positions()
gen.send(None)   # prime the generator

with open(sys.argv[1]) as f:
    for line in f:
        (seqid,seq) = line.strip().lower().split()
        slocs = gen.send(seq)
        print(seqid,slocs,"\n")

gen.close()  ## added to be more official

这是生成器

def find_start_positions (DNAstr = ""):

    DNAstr = DNAstr.upper()

    retVal = ()
    x = 0
    loc = -1

    locations = []

    while (x + 3) < len(DNAstr):

        if (DNAst[x:x+3] is "ATG" or DNAstr[x:x+3] is "GTG" ):
            loc = x

        if loc is not -1:
            locations.append(loc)

        loc = -1

    yield (tuple(locations))

这是错误:

Traceback (most recent call last):
  File "p3rmb.py", line 12, in <module>
    slocs = gen.send(seq)
StopIteration

【问题讨论】:

  • 是否打印出显示每一行的回溯?
  • Traceback(最近一次调用最后一次):文件“p3rmb.py”,第 12 行,在 slocs = gen.send(seq) StopIteration
  • 如果你调用sendyield需要被赋值。
  • @TylerDunn 我很难理解您在这里使用协程要完成的工作......
  • 顺便说一句,不要使用is 来比较字符串。这不是你想要的。

标签: python generator stopiteration


【解决方案1】:

您制作了一个可以一次返回所有数据的生成器。 您应该在每次迭代中产生数据。这段代码可能并不完美,但它可能会解决您的部分问题:

def find_start_positions (DNAstr = ""):
    DNAstr = DNAstr.upper()

    x = 0
    loc = -1

    while x + 3 < len(DNAstr):
        if DNAst[x:x+3] == "ATG" or DNAstr[x:x+3] == "GTG" :
            loc = x

        if loc is not -1:
            yield loc

        loc = -1

StopIteration 不是错误。这是生成器发出信号表示它用尽了所有数据的方式。您只需要“尝试排除”它,或者在已经为您执行此操作的 forloop 中使用您的生成器。 尽管它们并没有那么复杂,但可能需要一些时间来适应这些“奇怪”的错误。 ;)

【讨论】:

  • 不要使用is来比较字符串。
  • @juanpa.arrivillaga 好人!没有注意到,完全专注于生成器的东西。谢谢!
  • 每次在主函数中使用 gen.send() 时,变量 DNAstr 是否会改变?
  • 我还需要在每次收益后清除列表和东西吗?
  • @TylerDunn 该变量仅在方法内部更改,因为字符串、整数和元组等不可变参数是通过值而不是通过引用传递的。因此,您所做的更改将被丢弃。不必要。尽可能少地使用资源和变量是好的,但这不是强制性的。但是如果你清除了错误的东西,生成器可能会出现一些奇怪的行为。
【解决方案2】:

您的生成器在其整个生命周期内只返回一个值。它遍历while 循环,找到所有locations,并一举返回整个列表。因此,当您第二次调用send 时,您已经耗尽了生成器的操作。

您需要弄清楚每次调用send 的期望;配置你的循环以产生那么多,然后yield 那个结果......并为将来的send 调用继续这样做。您的 yield 语句必须在循环中才能正常工作。

Jayme 在他的回答中给了你一个很好的例子。

【讨论】:

    【解决方案3】:

    有一个内置的find() 函数可以在给定字符串中查找子字符串。这里真的需要生成器吗?

    相反,您可以尝试:

    import sys
    
    with open(sys.argv[1]) as f:
        text = f.read()
    
    for i, my_string in enumerate(text.strip().lower().split()):
        atg_index = my_string.find('atg')
        gtg_index = my_string.find('gtg')
        print(i, atg_index, gtg_index, my_string)
    

    【讨论】:

    • 我希望,但这是一项任务
    【解决方案4】:
    def find_start_positions (DNAstr = ""):
        DNAstr = DNAstr.upper()
    
        x = 0
        loc = -1
    
        while x + 3 < len(DNAstr):
            if DNAst[x:x+3] == "ATG" or DNAstr[x:x+3] == "GTG" :
                loc = x
    
            if loc is not -1:
                yield loc
    
            loc = -1
    

    【讨论】:

      猜你喜欢
      • 2019-02-14
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-02
      相关资源
      最近更新 更多