更好的方式来写这个"双管列表"在Python中

时间:2014-12-15 08:50:43

标签: python

第12行的for循环和嵌套在其中的for循环,我的意思是。我不止一次遇到过这样的情况。我使用列表理解,但它似乎不会在这里工作。

import random

import string

def password_generator():
    key = zip(string.digits, string.ascii_uppercase)

    cruft, x = str(random.random()).split('.')

    pw = ''

    for item in x:
        for element in key:
            if item in element:
                Q = random.random()
                if Q > 0.7:
                    pw += element[1].lower()
                else:
                    pw += element[1]

    print pw

感谢。

4 个答案:

答案 0 :(得分:3)

这是一种使用列表理解的方法:

def pw_gen():
    key = zip(string.digits, string.ascii_uppercase)

    cruft, x = str(random.random()).split('.')

    def f(i,e):
      Q = random.random()
      if Q > 0.7:
        return e[1].lower()
      else:
        return e[1]

    return [ f(item,element) for item in x for element in key if item in element ]

返回一个字符列表。使用"".join( pw_gen() )转换为字符串。

答案 1 :(得分:2)

我认为让你难以做到这一点的原因是你在循环中间得到了random.random()< 0.7部分。使它成为一个单独的函数,并且更容易将其转换为列表理解。

def f(str):
    if random.random()>0.7:
        return str.lower()
    else:
        return str

''.join([f(element[1]) for element in key for item in x if item in element])

答案 2 :(得分:2)

您可以使用itertools.product将这两者结合起来,但我觉得使用随机的更高级别方法可以简化此任务。

symbols=string.ascii_uppercase[:10]
pw = ''
for i in range(15):
  letter = random.choice(symbols)
  if random.random() > 0.7:
    letter = letter.lower()
  pw += letter

甚至更短:

symbols = (7*string.ascii_uppercase[:10] +
           3*string.ascii_lowercase[:10])
pw = ''.join(random.choice(symbols) for i in range(15))

您构建key的方式使其成为效率非常低的查找表。您可以替换几行以使用更有效的方法:

key = dict(zip(string.digits, string.ascii_uppercase))
#...
for item in x:
    letter = key[item]

不可否认,这些都会产生一个固定长度的密码,而你的字符串转换很少有机会获得更短的密码。但是,出于类似的原因,最后一位数字的随机性不如其他数字。

答案 3 :(得分:0)

与使用列表推导替换内部for循环相比,您的逻辑可以大大简化。这将等同于您的代码:

import random
import string
key = dict(zip(string.digits, string.ascii_uppercase))
cruft, x = str(random.random()).split('.', 1)
pw = ''
for item in x:
    if item in key: # This if is not required as all the single digits are present
        Q = random.random()
        if Q>0.7:
            pw += key[item].lower()
        else:
            pw += key[item]
print pw

但是,如果您确实希望密码是唯一的,并且不需要轻松进行逆向工程,我建议您使用UUID。如果您想要一个更好的密码生成器(带有字母数字和符号),您可以执行this之类的操作。

请注意,它不是官方的python网站,也可以通过多种方式进行改进。像往常一样,我的意思是to shoot,以任何方式使用它。