В настоящее время я работаю над одним из наборов проблем на MIT OCW, задача состоит в том, чтобы найти соответствующие подстроки в последовательностях ДНК.Функции генератора в Python
Я изо всех сил пытаюсь написать функцию, которая возвращает подпоследовательности длины k. Я могу заставить его работать при использовании строки, но проблема связана с итератором. При использовании итератора функция, похоже, каждый раз перезагружается, а не возвращается в исходное положение с выходом.
Вот правильная функция, которую я написал, что использует строку:
def subs(seq, k):
subseq = ''
pos = 0
while pos < len(seq):
while len(subseq) < k:
subseq += seq[pos]
pos += 1
yield subseq, pos - k
subseq = subseq[1:]
Правильный ответ:
>>> a = 'hello'
>>> b = subs(a,2)
>>> b.next()
('he', 0)
>>> b.next()
('el', 1)
>>> b.next()
('ll', 2)
>>> b.next()
('lo', 3)
>>> b.next()
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
b.next()
StopIteration
Моя проблема
Задача устанавливается с помощью класс, который создает итератор из длинной последовательности строк, я не буду вдаваться в него здесь, но приведенный тест также создает итератор из строки
# This test case may break once you add the argument m (skipping).
class TestExactSubmatches(dnaseq.unittest.TestCase):
def test_one(self):
foo = 'yabcabcabcz'
bar = 'xxabcxxxx'
matches = list(dnaseq.getExactSubmatches(iter(foo), iter(bar), 3, 1))
correct = [(1,2), (4,2), (7,2)]
self.assertTrue(len(matches) == len(correct))
for x in correct:
self.assertTrue(x in matches)
и мое текущее решение:
def subsequenceHashes(seq, k):
subseq = ''
pos = 0
print 'Start of subseqHashes'
try:
while True:
while len(subseq) < k:
subseq += seq.next()
pos += 1
print subseq, pos - k
yield hash(subseq), pos - k
subseq = subseq[1:]
except StopIteration:
return
Функция вызова он получает хэш подпоследовательности, помещает их вместе с положением, где подпоследовательности начинается в словарь (класс multidict) и сравнивает подстроки с одним и тем же хешем, чтобы увидеть, совпадают ли они. Затем он должен возвращать пары позиций в обеих строках подстрок, которые являются одинаковыми. Мне не удалось отладить большую часть этой функции, поскольку у меня возникают проблемы с ее запуском.
def getExactSubmatches(a, b, k, m):
# a and b are the strings compared, k is the length of substring, parameter m is unused, need it for later on in the problem set
ahash, apos = subsequenceHashes(a, k).next()
bhash, bpos = subsequenceHashes(b, k).next()
multidict = Multidict()
print 'starting'
while ahash:
print 'iterate'
multidict.put(ahash, ('a', apos))
ahash, apos = subsequenceHashes(a, k).next()
print apos
while bhash:
multidict.put(bhash, ('b', bpos))
bhash, bpos = subsequenceHashes(b, k).next()
for key in multidict.mydict:
if len(multidict.get(key)) > 1:
for t in multidict.get(key):
if t[0] == 'a':
for s in multidict.get(key):
if s[0] == 'b':
if a[apos:apos+k] == b[bpos:bpos+k]:
print apos, bpos
yield apos, bpos
Что происходит, когда я запускаю тест:
Start of subseqHashes
yab 0
Start of subseqHashes
xxa 0
starting
iterate
Start of subseqHashes
cab 0
0
iterate
Start of subseqHashes
cab 0
0
iterate
Start of subseqHashes
F..
======================================================================
FAIL: test_one (__main__.TestExactSubmatches)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\Alex\Desktop\Pythonwork\6.006\ps4\dist\test_dnaseq.py", line 32, in test_one
self.assertTrue(len(matches) == len(correct))
AssertionError: False is not true
Что, кажется, идет не так как subsequenceHashes в настоящее время сбрасываются каждый раз, когда я использую .next(), когда его получил итератор в своем теле, как против того, чтобы оставаться в цикле при использовании строки.
Каждый раз, когда вы звоните, например. 'sequenceenceHashes (b, k)' он начнется снова. Вы должны создать их один раз, в начале функции. – jonrsharpe
Последовательности ДНК, которые я буду сравнивать, составляют десятки миллионов нуклеотидов в длину, набор проблем рекомендует делать функции генератора. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/assignments/MIT6_006F11_ps4.pdf – Az00123
Да, но вы должны * только звонить функция генератора один раз *. После этого вы хотите только * перебрать его *, не перезапускать его. Начните с 'gen_a = sequenceenceHashes (a, k)' и идите оттуда. – jonrsharpe