¿Por qué re.findall no es específico en la búsqueda de elementos de triplete en una cadena? Pitón

Así que tengo cuatro líneas de código

seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA' OR_0 = re.findall(r'ATG(?:...){9,}?(?:TAA|TAG|TGA)',seq) 

Déjame explicarte lo que estoy tratando de hacer primero. . . Lo siento si esto es confuso pero voy a hacer mi mejor esfuerzo para explicarlo.

Así que estoy buscando secuencias que comiencen con ‘ATG’ seguido de unidades de 3 de cualquier palabra char [por ejemplo, ‘GGG’, ‘GTT’, ‘TTA’, etc.] hasta que encuentre un ‘TAA’, ‘TAG’ o ‘TGA’ también quiero que tengan al menos 30 caracteres. . . por lo tanto el {9,}?

Esto funciona hasta cierto punto, pero si se da cuenta de que hay ATG GAA GTT GGA TGA AAG TGG AGG TAA AGA GAA GAC GTT TGA

Entonces, en este caso, debería estar encontrando ‘ATGGAAGTTGGATGA’ si comienza con el primer ‘ATG’ y continúa hasta el siguiente ‘TAA’, ‘TAG’ o ‘TGA’

SIN EMBARGO, cuando ejecuta la línea de código OR_0, escupe nuevamente toda la cadena de secuencia. No sé cómo hacerlo, solo considere el primer ‘TAA’, ‘TAG’ o ‘TGA’ seguido del primer ‘ATG’

Si un ‘ATG’ es seguido por otro ‘ATG’ cuando se lee en unidades de 3, entonces eso está bien, NO debe comenzar de nuevo, pero si encuentra un ‘TAA’, ‘TAG’ o ‘TGA’ cuando se lee en unidades de 3 debería detenerse

Mi pregunta, ¿por qué es posible encontrar la secuencia más larga de ‘ATG’xxx-xxx – [‘ TAA ‘,’ TAG ‘o’ TGA ‘] en lugar de la primera aparición de’ TAA ‘,’ TAG ‘o’ TGA ‘? ¿Después de un ATG separado por caracteres de palabras en unidades de 3?

Una vez más, pido disculpas si esto es confuso, pero es un lío con múltiples conjuntos de datos que he basado en esta línea de texto inicial y estoy tratando de averiguar por qué

Si desea que su expresión regular deje de coincidir en el primer TAA|TAG|TGA , pero aún así tenga éxito si hay al menos nueve fragmentos de tres letras, lo siguiente puede ayudar:

 >>> import re >>> regexp = r'ATG(?:(?!TAA|TAG|TGA)...){9,}?(?:TAA|TAG|TGA)' >>> re.findall(regexp, 'ATGAAAAAAAAAAAAAAAAAAAAAAAAAAATAG') ['ATGAAAAAAAAAAAAAAAAAAAAAAAAAAATAG'] >>> re.findall(regexp, 'ATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAG') ['ATGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAG'] >>> re.findall(regexp, 'ATGAAATAGAAAAAAAAAAAAAAAAAAAAATAG') [] 

Esto utiliza un lookahead negativo (?!TAA|TAG|TGA) para garantizar que un fragmento de tres caracteres no sea un TAA|TAG|TGA antes de que coincida con el fragmento de tres caracteres.

Sin embargo, tenga en cuenta que un TAA|TAG|TGA que no cae en un límite de tres caracteres aún coincidirá con éxito:

 >>> re.findall(regexp, 'ATGAAAATAGAAAAAAAAAAAAAAAAAAAATAG') ['ATGAAAATAGAAAAAAAAAAAAAAAAAAAATAG'] 

Si la longitud no es un requisito, entonces es bastante fácil:

 >>> import re >>> seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA' >>> regex = re.compile(r'ATG(?:...)*?(?:TAA|TAG|TGA)') >>> regex.findall(seq) ['ATGGAAGTTGGATGA'] 

De todos modos, creo que, según su explicación, su regex anterior está haciendo lo que usted quiere: buscar coincidencias de al menos 30 caracteres que comiencen en ATG y terminen en TGA .

En tu pregunta, primero dices que necesitas coincidencias de al menos 30 caracteres, y por lo tanto, ¿colocas el {9,}? , pero después de eso esperas igualar cualquier partido. No puedes tener ambos, elige uno. Si la longitud es importante que mantener la expresión regular que ya tiene y el resultado que está obteniendo es correcto .

No necesitas expresiones regulares.

 def chunks(l, n): """ Yield successive n-sized chunks from l. from: http://stackoverflow.com/a/312464/1561176 """ for i in xrange(0, len(l), n): yield l[i:i+n] def method(sequence, start=['ATG'], stop=['TAA','TAG','TGA'], min_len=30): response = '' started = False for x in chunks(sequence, 3): if x in start: started = True response += x elif x in stop and started: if len(response) >= min_len: yield response + x response = '' started = False else: response += x elif started: response += x yield response for result in method('ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA'): print result 

Si uso el min_len de 30, el retorno es:

 ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA 

Si uso un min_len de 0, el retorno es:

 ATGGAAGTTGGATGA 

Prueba esto:

 seq= 'ATGGAAGTTGGATGAAAGTGGAGGTAAAGAGAAGACGTTTGA' OR_0 = re.findall(r'ATG(?:.{3})*?(?:TAA|TAG|TGA)',seq)