Reputation: 353
The for loop at line 12 and the one nested within it, I mean. I've encountered situations like this more than once. I'd use a list comprehension but it doesn't seem like it would work here.
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
Thanks.
Upvotes: 3
Views: 85
Reputation: 23827
What I think is making it hard for you to do this is that you've got the random.random()<0.7 part in the middle of the loop. Make that a separate function, and it's easier to turn it into a list comprehension.
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])
Upvotes: 2
Reputation: 15877
You can use itertools.product to combine those two, but I get the feeling this task could be simplified using a higher level method from 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
Or even shorter:
symbols = (7*string.ascii_uppercase[:10] +
3*string.ascii_lowercase[:10])
pw = ''.join(random.choice(symbols) for i in range(15))
The way you're building key
makes it a very inefficient lookup table. You could replace a few lines to use a more efficient method:
key = dict(zip(string.digits, string.ascii_uppercase))
#...
for item in x:
letter = key[item]
Admittedly these all produce a fixed length password, and your string conversion had a small chance of getting a shorter number. For similar reasons, though, the last digit was less random than the others.
Upvotes: 2
Reputation: 4250
Your logic can be lot simplified than using a list comprehension to replace the inner for loop. This will be the equivalent of your code:
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
However, I would suggest you to go with UUID if you really want the password to be unique and not required to reverse engineer easily. If you want a better password generator(with alphanumeric and symbols), you can do something like this.
Please note that it is not an official python site and also it can be improved in many ways. As usual, it will be your call to shoot, I mean, to use it in any way.
Upvotes: 0
Reputation: 52039
Here's a way to use a list comprehension:
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 ]
This returns a list of characters. Use "".join( pw_gen() )
to convert to a string.
Upvotes: 3