2017-06-20 3 views
1

Je suis en train d'écrire un programme qui prend en entrée d'un fichier et chaque ligne peut contenir des « ATG » ou « GTG » et je suis assez sûr que je l'ai fait tout droit dans la mesure ce que j'essaie de faire. C'est la première fois que j'utilise un générateur en python et après avoir fait des recherches sur ce problème, je ne sais toujours pas pourquoi j'arrête l'itération. Pour cela, mon générateur doit générer un tuple avec les emplacements de départ pour ATG ou GTG trouvés dans chaque chaîne.Je ne sais pas pourquoi je reçois erreur StopIteration

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 

C'est le générateur

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

Ceci est l'erreur:

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

est-il un retraçage imprimé montrant chaque ligne? – JacobIRR

+0

Traceback (dernier appel en dernier): Fichier "p3rmb.py", ligne 12, en slocs = gen.send (seq) StopIteration –

+0

Si vous appelez 'send', vous devez affecter' yield' à une valeur. –

Répondre

2

Vous avez fait un générateur qui renvoie toutes les données à la fois. Vous devez générer les données à chaque itération. Ce code peut ne pas être parfait, mais il peut résoudre une partie de votre problème:

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 

Le StopIteration n'est pas une erreur. C'est la façon dont un générateur signale qu'il a épuisé toutes ses données. Vous avez juste besoin de "l'essayer sauf" ou d'utiliser votre générateur dans un forloop qui le fait déjà pour vous. Bien qu'ils ne soient pas si compliqués, cela peut prendre un certain temps pour s'habituer à ces erreurs «bizarres». ;)

+1

N'utilisez pas 'is' pour comparer des chaînes. –

+1

@ juanpa.arrivillaga Sûr homme! Je n'ai pas remarqué cela, concentré complètement sur les trucs du générateur. Je vous remercie! –

+0

Est-ce que le DNAstr variaable est modifié à chaque fois que gen.send() est utilisé dans la fonction principale? –

2

Votre générateur est conçu pour renvoyer une seule valeur pendant toute sa durée de vie. Il parcourt la boucle while, trouve tous les locations et renvoie cette liste entière d'un seul coup. Ainsi, lorsque vous appelez send une seconde fois, vous avez épuisé les opérations du générateur.

Vous devez savoir ce que vous attendez de chaque appel de send; configurez votre boucle pour produire juste cela, et puis yield qui en résulte ... et continuez à le faire pour les futures invocations send. Votre instruction yield doit être dans une boucle pour que cela fonctionne.

Jayme vous a donné un excellent exemple dans sa réponse.

0

Il y a une fonction find() intégrée pour trouver une sous-chaîne dans une chaîne donnée. Un générateur est-il vraiment nécessaire ici?

Au lieu de cela, vous pouvez essayer:

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) 
+0

Je souhaite mais c'est une mission –