2014-01-21 41 views
0

我想將一個字符串拆分成隨機大小的小塊。例如,Python爲循環的每次迭代生成範圍函數的隨機步驟

string = 'qwertyuiopp'['qw','e','rty,'u','iopp']

for record in SeqIO.parse(args.fasta_file , "fasta"): 
    step = 200 
    for i in range(0, len(record),step): 
     oline = ">"+record.id+"_"+str(i+1)+"\n" 
     ofname.write(oline) 
     step = random.randrange(200,2000) 
     if len(record.seq[i:i+step]) >= 200: 
      oline= str(record.seq[i:i+step])+"\n" 
      ofname.write(oline) 
     i=i+step 
     else: 
      oline= str(record.seq[i-200:])+"\n" 
      ofname.write(oline) 
     i=len(record)+1 

我的數字的問題是,在範圍函數的步驟仍然是修改使用randrange步長的值的常數(200)inspite。但我不知道我應該如何去做這件事。感謝任何幫助。

+0

嘗試random.randint(200,2000)代替random.randrange(200,2000)。 –

+0

爲什麼不簡單地生成隨機數的隨機索引,對生成的索引進行排序,然後構建子串? – Bakuriu

+0

@Bakuriu:用這種方法獲得相同的分佈並不是微不足道的。 – abarnert

回答

3

range函數只要遇到for循環就會創建一個列表。它不會爲每次迭代進行評估。 您可以使用while循環來實現此目的。

import random 
step = 1 
count = 0 
while count < len(record):  
    print count 
    step = random.randint(1, 5) 
    count += step 
+0

這僅適用於Python 2.x.在3.x中,'range'創建一個'range'對象,而不是'list'。但效果是一樣的:你得到一個'range(0,1000,200)'對象,當step改變時它不會奇蹟般地改變自己。 – abarnert

2

range函數不記得它是如何得到它的構造值的。當你調用range(0, len(record), step)創建範圍對象range(0, 1000, 200)(Python 3.x)或者列表[0, 200, 400, 600, 800](Python 2.x)。無論哪種方式,以後更改step都不會改變任何內容。

您可以構建一個自定義迭代器,讓您重置其步驟,或者更改其步驟並迭代(start, end)(start, step)對的步驟。但是這可能對你有一些進步*

在這種情況下,當你找不到或者寫一個迭代器來循環時,你必須去一個while循環,然後手動更新你的循環變量。

值得注意的是,你已經試圖手動更新你的循環變量,與i = i + step。在for循環中這通常是一個糟糕的主意 - 但在while循環中,這正是您想要的。所以真的,只是改變這一行:

for i in range(0, len(record),step): 

...這兩行:

i = 0 
while i < len(record): 

有代碼中的其他問題,你必須修復(包括至少兩個IndentationError S),但一旦你過去了,你可以修復它們。

最後一兩件事:無論你已經有了一個for環或while循環,如果你想早點打出來,要做到這一點是break聲明,而不是試圖改變循環條件,所以未來測試將失敗。所以,最後用break替換i=len(record)+1


*另外,對於這樣一個迭代器的明顯實現將是同一種while環反正...

+0

這個答案的解決方案已經在senshin的解決方案的大部分解釋中。不幸的是,他刪除了他的答案,所以我不能僅僅提到它。 – abarnert

+0

@abernert非常感謝您提供這個詳盡的答案,並且也指出了我的代碼中的問題。 – user2960593