findall
метод возвращает список совпадений. Если шаблон содержит группы захвата, то каждое совпадение является кортежем строк, соответствующих каждой группе захвата в шаблоне.
От the documentation:
Возврата непересекающихся матчей pattern
в string
, в виде списка строк. string
сканируется слева направо, а совпадения возвращаются в найденном порядке. Если одна или несколько групп присутствуют в шаблоне, верните список групп; это будет список кортежей, если шаблон имеет более одной группы. Пустые совпадения включаются в результат, если они не касаются начала другого матча.
Ваш шаблон содержит три группы захвата. Группы вложены. Первой (и самой внешней) группой является весь шаблон, (ATG((\w\w\w)*)(?!TAA))
. Вторая группа - ((\w\w\w)*)
. Третья группа - (\w\w\w)
.
Обратите внимание, что отрицательное утверждение, (?!TAA)
, is не группа захвата.
По сути, ваш рисунок говорит, что он соответствует кодону ATG
, за которым следует как можно больше кодонов, но резервное копирование двух кодонов, если совпадение остановится на кодоне TAA
. Поскольку *
жадный, ваш шаблон будет соответствовать кодону посередине. Он отклонит только кодон TAA
(и кодон до этого), если TAA
встречается в конце входной строки.
Из-за ваших групп захвата ваш паттерн говорит, что каждое возвращаемое совпадение должно содержать три строки: всю последовательность согласованных кодонов, последовательность согласованных кодонов, исключая начальный , и последний согласованный кодон в последовательности.
Вы можете отметить группу в качестве не-захвата с использованием (?:...)
, как это:
In [5]: pat = re.compile("(?:ATG(?:(?:\w\w\w)*)(?!TAA))")
Если шаблон не содержит захватив группы, затем findall
возвращается каждый матч как одну строку, вместо того, как кортеж.
In [6]: pat.findall(s)
Out[6]: ['ATGCCTAAG']
Если вы хотите остановиться в первойTAA
, но идти до конца строки, если нет TAA
на всех, вы должны проверить каждый кодон, наложив свое отрицательное опережения утверждение внутри повторение:
pat = re.compile("ATG(?:(?!TAA)\w\w\w)*")
Это утверждает, на каждый кодон после первоначального ATG
, что оно не должно совпадать с TAA
кодоном.
Если вы хотите остановиться на первом TAA
кодона, даже если кодон не совпадает с ATG
, вы можете сделать это следующим образом:
In [7]: pat = re.compile("ATG(?:(?!.{0,2}TAA)\w\w\w)*")
In [8]: pat.findall(s)
Out[8]: ['ATG']
In [10]: pat.findall('ATGCCTGAATATAAG')
Out[10]: ['ATGCCTGAA']
как заставить искать только для всего шаблона, но не подшаблоны? – ashim
Я обновил свой ответ. –
(?! TAA) не должен включать TAA, но в конечном итоге он включен, почему? – ashim