2014-10-07 65 views
1

我已經在python 3.4中編寫了一個簡單的詞表生成器,我還在學習,所以它不是最好的代碼,但我只是想更深入和理解語言和它的邏輯,首先這裏是我的代碼:在Python 3.4中增強我的代碼(Wordslist生成器)

import random 
letters = ['a','b','c','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0'] 
wordslist = [] 
def Generate_words(_from,_to,_length): 
    while _from <= _to: 
     random_word = _length*random.choice(letters) 
     if (random_word) in (wordslist): 
      print ("Word already exists, looking for another one..") 
     else: 
      wordslist.append(random_word) 
      print ("total of "+str(_from)+" generated word(s) added to wordlist..") 
      progress = _from/_to*100 
      print ('total progress is: '+str(progress)+'%') 
      _from = _from+1 

    if _from > _to: 
     print ("Wordslist generated: ") 
     print (wordslist) 

Fnumber = input ("Enter the total number of words you want to generate: ") 
Snumber = input ("Enter the length of each word: ") 
Generate_words(1,int(Fnumber),int(Snumber)) 
Exit = input("Press any key to exit") 

現在我知道,這條線:random_word = _length * random.choice(字母)會產生相同的字母X號,這是第一個問題,我正在努力解決。 我試圖做的第二件事是找到一種方法,防止腳本生成一個以前生成的單詞,這將使它更快,更高效

回答

2

你的代碼工作正常,除了_length*random.choice(letters)行。你真正想要的是每次選擇一個新的隨機字符。這可以通過兩種方式完成。你可以只使用一個循環:

random_word = '' 
for j in range(_length): 
    random_word += random.choice(letters) 

然而,這是做的相當醜陋的方式,因爲你是(1)追加爲一個字符串,這是低效和(2)不利用一Python的半獨特功能,一個list comprehension

更好的方法是使用列表理解和str.join()方法。

random_word = ''.join((random.choice(letters) for i in range(length)) 

此外,當您要檢查是否東西是一個集合中,一個set比列表更好的選擇(這是更快檢查會員)。

因此,wordslist = []變成wordlist = set()wordlist.append(random_word)變成wordlist.add(random_word)

您可以從string庫中獲得小寫字母和數字的列表,因此您不必手動輸入它們。所以:letters = ['a', 'b'...]變成letters = string.ascii_lowercase + string.digits。請注意,生成的對象是一個字符串,而不是一個列表,但對我們來說,這並不重要。

代碼中還有一些小樣式問題,例如用大寫字母開始變量名稱。更重要的是,以_開頭的名稱在Python中具有特殊意義,它們通常表示變量是私有的(並且不意味着在其類之外使用)。按照PEP8中概述的指導原則,通常是個好主意。我修復了這些並稍微改變了一些其他的東西。完整的代碼粘貼在下面。如果您有任何問題,我很樂意進一步澄清這些細微變化。

import random 
import string 

letters = string.ascii_lowercase + string.digits 
wordslist = set() 

def generate_words(number, length): 
    i = 0 
    while i < number: 
     random_word = ''.join(random.choice(letters) for i in range(length)) 
     if random_word in wordslist: 
      print("Word already exists, looking for another one..") 
     else: 
      wordslist.add(random_word) 
      print("total of "+str(i+1)+" generated word(s) added to wordlist..") 
      progress = (i+1)/number*100 
      print ('total progress is: '+str(progress)+'%') 
      i += 1 
    else: 
     print("Wordslist generated: ") 
     print(wordslist) 

if __name__ == '__main__': 
    f_number = input ("Enter the total number of words you want to generate: ") 
    s_number = input ("Enter the length of each word: ") 
    generate_words(int(f_number),int(s_number)) 
    input("Press any key to exit") 

編輯:有沒有在for循環,會造成如果重複被發現會產生少言的錯誤。現在修復。

+0

這正是我所期待的。感謝您的回覆,非常感謝 – q8mind 2014-10-07 19:55:22

0

首先,按照慣例,函數和變量名稱不應該啓動用大寫字母。這是保留給類。話雖這麼說,你的問題:

1.

的整數乘以一個字符串的產品中含有非常串的頻率重複操作暗示。當您的表達式random.choice(letters)首先被評估時,乘法將會簡單地重複其結果。要創建的隨機字符的列表,它必須是:

random_chars = [random.choice(letters) for i in range(_length)] 

...它可以摺疊成一個字符串使用:

random_word = ''.join(random_chars) 

2.

而不是使用列表如果查詢性能較差,請將您的文字放到字典中進行對數查找時間:

wordslist = {} 
#... 
if wordslist.get(random_word): 
#... 
wordslist[random_word] = True 
+1

在這種情況下,'set()'優於'dict()',因爲我們只想要成員檢查。 – 2014-10-07 19:41:48

+0

好點。我已經領先一步,考慮維護自定義字典結構以便在生成過程中進行實時查詢。 +1爲您精心設計,符合python3的答案! – 2014-10-07 19:59:27

0

您的代碼是非常接近工作!

我唯一改變的是你的線random_word = _length*random.choice(letters)

我改成

random_word = '' #we need a new random_word for each iteration of the loop 
    for index in range(0,_length): #we need our words to be _length long 
     random_word += random.choice(letters) #add a new letter to our random word 

基本上,發生的事情是,你random_word是說:「選擇一個隨機的信,和任何的長度單詞是,把它們中的n個彼此相鄰「。因此,你總是得到「xx」,「00」,「ff」等你的話。

我的代碼的區別在於它實際上選取了n個隨機字母。你的代碼挑選一個隨機字母,並將它們連接在一起。

至於防止它產生一個以前生成的詞,這可能是一個有點太多的理論在這裏,但這是不可能的....如果你知道你不能產生的東西,那麼什麼你生成的並不是隨機的。