在Python中更好的编写“双管齐下列表”的方式

3

我是指第12行的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个回答

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() )将其转换为字符串。


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
你可以使用itertools.product来组合这两个,但我感觉使用random中的更高级别的方法可能会简化这个任务。
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]

可以承认,这些都会产生一个固定长度的密码,而您的字符串转换有一定几率得到一个较短的数字。出于类似的原因,最后一位比其他位更不随机。

这(random.choice示例)是一种更优越的(即更符合Python风格的)做法。Python哲学的一部分是:“应该有一种——最好只有一种——明显的方法来做到这一点”,而这在很大程度上依赖于“电池内置”(并使用它们!!!)。 - mac

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接