2014-10-07 102 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个随机字母。你的代码挑选一个随机字母,并将它们连接在一起。

至于防止它产生一个以前生成的词,这可能是一个有点太多的理论在这里,但这是不可能的....如果你知道你不能产生的东西,那么什么你生成的并不是随机的。