生成随机密码
from  random  import  choice
import  string

def  GetPasswd(length = 8 ,chars = string.letters + string.digits):
    
return   '' .join([choice(chars)  for  i  in  range(length)])

for  i  in  range( 6 ):
    
print  GetPasswd( 12 )
这样生成的是完全随机的密码
例如
Q9uSQLqRZD8v
hkxuEQLMz09P
7ep913f99c0Z
6rMvzFcVQQWJ
LllA5dVPhp2J
fn5DrV33N6g6

那么如何生成易记的伪随机密码呢?
import  random,string,os
class  password(object):
    
# 任何含有大量单词的文件都可以:我们只想让self.data
     # 成为一个大字符串,我们将模仿其中的文本
     print  os.getcwd()
    data
= open( " words.txt " ).read().lower()
    
def  renew(self,n,maxmem = 3 ):
        
''' 根据回溯的最大“历史”的maxmem个字符
             在self.data中累积n个随机字符
'''
        self.chars
= []
        
for  i  in  range(n):
            
# 随机“旋转”self.data
            randspot = random.randrange(len(self.data))
            
# print "randspot=",randspot
            self.data = self.data[randspot:] + self.data[:randspot]
            
# print "self.data=",self.data
             # 获得n-gram
            where =- 1
            
# 试图定位self.data中最后maxmem个字符
             # 如果i<maxmem,我们其实只获取最后i个
             # 即使是所有self.chars也没问题:列表
             # 切片的容忍度很高,仍然适合此算法
            locate = '' .join(self.chars[ - maxmem:])
            
# print "locate=",locate
             while  where < and  locate:
                
# 定位data中的n-gram
                where = self.data.find(locate)
                
# print "where=",where
                 # 如果必要的话后退到一个短一点的n-gram
                locate = locate[ 1 :]
                
            
# 如果where=-1且locate='',选self.data[0]
             # 那是self.data中随机的一项,因此旋转过
            c = self.data[where + len(locate) + 1 ]
            
# print "c=",c
             # 我们只需要小写字母,所以,如果我们挑到了
             # 大写字母,我们会再次随机选择一个字母
             if   not  c.islower():c = random.choice(string.lowercase)
            
# 最后我们将字母记录到self.chars
            self.chars.append(c)
    
def   __str__ (self):
        
return   '' .join(self.chars)
    
if   __name__ == ' __main__ ' :
# for test
     # onepass=password()
     # onepass.renew(5,2)
     # print onepass.chars

    
" 使用方法:pastiche [passwords [length [memory]]] "
    
import  sys
    
if  len(sys.argv) > 1 : dopass = int(sys.argv[ 1 ])
    
else :dopass = 8
    
if  len(sys.argv) > 2 : length = int(sys.argv[ 2 ])
    
else :length = 10
    
if  len(sys.argv) > 3 : memory = int(sys.argv[ 3 ])
    
else :memory = 3

    onepass
= password()
    
for  i  in  range(dopass):
        onepass.renew(length,memory)
        
print  onepass
    
我理解的流程:
打乱单词库(循环,并非实际的打乱,相对位置没变)→找到已选单词的最后maxmem个字母(不够则找i个)→在单词库里查找位置→没有出现过则找最后maxmem-1个字母→出现过则将后面的这个字母加到已选单词列表里面。
以下照抄cookbook:
我们在挑选每个字母的时候必须参考前面几个已经被挑选的字母。因此,生成密码的过程实际上是根据用户熟悉的模式来重复的挑选字母。
每次基于前maxmem个已选的字符挑选下一个字符。由于在子串中找到第一个位置总是很容易的,代码会随机的“旋转”所有文本字符串,以确保从原文的角度看第一个位置也是随机的。如果由最后maxmem个字符构成的子字符串在文本中找不到,代码会“回退”一步,搜寻由最后的maxmem-1字符构成的子串,以此类推,在最坏的情况下,代码会一直回退,最后直接选择旋转过的文本的第一个位置(从原文的角度看这仍然是一个随机的字符)。
当选择流程找出了一个非小写字母的字符,马尔科夫链进程就会被打断,在这种情况下,程序会随机选个小写字母。