2015-01-05 3 views
1

В настоящее время я работаю над одним из наборов проблем на 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(), когда его получил итератор в своем теле, как против того, чтобы оставаться в цикле при использовании строки.

+1

Каждый раз, когда вы звоните, например. 'sequenceenceHashes (b, k)' он начнется снова. Вы должны создать их один раз, в начале функции. – jonrsharpe

+0

Последовательности ДНК, которые я буду сравнивать, составляют десятки миллионов нуклеотидов в длину, набор проблем рекомендует делать функции генератора. http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-fall-2011/assignments/MIT6_006F11_ps4.pdf – Az00123

+0

Да, но вы должны * только звонить функция генератора один раз *. После этого вы хотите только * перебрать его *, не перезапускать его. Начните с 'gen_a = sequenceenceHashes (a, k)' и идите оттуда. – jonrsharpe

ответ

0

Как упоминалось в @jonrsharpe, моя ошибка вызывала функцию генератора несколько раз и фактически не повторялась.

Смежные вопросы