Okay, I'm done with making a lot of threads with nooby quesions. Those were just some things in the back of my mind. But that's not the point. Here's a program that generates a random 8 character string. It consists of letters A-Z, a-z, and 1-9. There's 767,544,201,216 possible combinations. It could possibly be used to keep bots\macros from using a program or repeatedly doing something. But enough talking, here's the code:

``````from random import *

def randstr():

#Generates a random string.
#String consists of numbers 1-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#767,544,201,216 possible combinations

lower = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")
upper = ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")

ch = randint(1,2)
if ch == 1:
case1 = lower
else:
case1 = upper

del ch

ch = randint(1,2)
if ch == 1:
case2 = lower
else:
case2 = upper

del ch

ch = randint(1,2)
if ch == 1:
case3 = lower
else:
case3 = upper

del ch

ch = randint(1,2)
if ch == 1:
case4 = lower
else:
case4 = upper

del ch

test1x = choice(case1)
test2x = choice(case2)
test3x = choice(case3)
test4x = choice(case4)
test1y = randint(1,9)
test2y = randint(1,9)
test3y = randint(1,9)
test4y = randint(1,9)
strconv1 = str(test1y)
strconv2 = str(test2y)
strconv3 = str(test3y)
strconv4 = str(test4y)
shuffled = [test1x, strconv1, test2x, strconv2, test3x, strconv3, test4x, strconv4]
shuffle(shuffled)
count = 0
for number in shuffled:

if count == 0:
sub_set = number
count = count+1

if count == 8:
rand = sub_set
quit

if count != 0:
if count != 8:
sub_set = sub_set+number
count = count+1

print (rand)
del test1x
del test2x
del test3x
del test4x
del test1y
del test2y
del test3y
del test4y
del strconv1
del strconv2
del strconv3
del strconv4
del shuffled
del count
del rand
del sub_set
del number
input ()

randstr()``````

I just started python about a week ago and I'm learning a lot! Also, I added the del commands because if it were to be used as a function you wouldn't want to leave variables laying around like that.
EDIT:
I edited it so it del the variables before the input. I don't know why but I just felt like doing it that way.

Take a looky here:

``````import string

print(string.digits)
print(string.ascii_lowercase)
print(string.ascii_uppercase)

# optional ...
#help(string)``````

Also, all your many deletes are not needed, since variables are handled very well by Python's excellent built-in memory manager. On top of that, the variables in functions are local and are deleted after the function is done anyway.

What you consider a variable is simply an identifier of an object in Python and gets used for other objects if need be. Identifiers are part of an internal dictionary with identifier:object pairs. Since the identifier is a dictionary key, only one unique name can exist.

Wow, I knew about ascii_letters and stuff but I didn't think they could be used with choice(). The var information was helpful too! Thanks a million :).

Wow, I knew about ascii_letters and stuff but I didn't think they could be used with choice(). The var information was helpful too! Thanks a million :).

FYI,
upper = list(string.ascii_uppercase)

Yeah, I figured that out, but thanks any way. Here's the "redone" version. I also used much shorter variables. Not only that, but in the last one it used 4 numbers and 4 letters, in this it can use any amount of each. So now it's truly random with a whopping
218,340,105,584,896 possible combinations. Anyway, here's the code:

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

def randstr():

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def digit_letter():

global dig_let
dig_let = randint(1,2)
if dig_let == 1:
dig_let = digits
else:
dig_let = ascii_letters

digit_letter()
x1 = choice(dig_let)

digit_letter()
x2 = choice(dig_let)

digit_letter()
x3 = choice(dig_let)

digit_letter()
x4 = choice(dig_let)

digit_letter()
y1 = choice(dig_let)

digit_letter()
y2 = choice(dig_let)

digit_letter()
y3 = choice(dig_let)

digit_letter()
y4 = choice(dig_let)

count = ""

shuffled = [x1, y1, x2, y2, x3, y3, x4, y4]
shuffle(shuffled)

for number in shuffled:

if count == "":
count = 0
sub_set = number
count = count+1

if count == 8:
rand = sub_set
quit

if count != 0:
if count != 8:
sub_set = sub_set+number
count = count+1

print (rand)
input ()

randstr()``````

If this is your first python program, it's quite good. Congratulations ! Note however that you're using 8 times the same pair of statements

``````digit_letter()
x1 = choice(dig_let)``````

to create the list 'shuffled'. In a good program, you should not repeat 8 times the same sequence of statements. Instead, you could populate the list with a loop

``````shuffled = list() # or shuffled = []
for i in range(8):
shuffled.append(choice(digit_letter()))``````

Also, it's not a good idea to have variables named x1, x2, x3, x4. In such cases, it's better to use a list. For example you can create a list of length 4 like this

``x = list(range(4))``

Then use `x[0], x[1], x[2], x[3]` instead of `x1, x2, x3, x4` . A good reason to do this is that you can later traverse the sequence of values with a loop, for example

``````for val in x:
print(val)``````

``````for val in (x1, x2, x3, x4):
print(val)``````
commented: Very helpful, learned something new! +1

I never thought of it that way. Using a for loop to create the list would make perfect sense. I also never new of the .append function before. BTW This is actually my second program, but yeah, I did have to work on it a bit :).

For some reason it wouldn't let me edit my post above, but anyway, here's the finished product:

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

def randstr():

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def digit_letter():

global dig_let
dig_let = randint(1,2)
if dig_let == 1:
dig_let = digits
else:
dig_let = ascii_letters

global shuffle
shuffled = list()
x = list(range(4))
for d in range(8):
digit_letter()
shuffled.append(choice(dig_let))

shuffle(shuffled)
count = ""

for number in shuffled:

if count == "":
count = 0
sub_set = number
count += 1

if count == 8:
rand = sub_set
quit

if count != 0:
if count != 8:
sub_set += number
count += 1

print (rand)
input ()

randstr()``````

Is there any suggestions on improvement? Or is that already efficient enough. BTW The structure of this for loop:

``````for number in shuffled:

if count == "":
count = 0
sub_set = number
count += 1

if count == 8:
rand = sub_set
quit

if count != 0:
if count != 8:
sub_set += number
count += 1``````

Came from one of my bath projects, except in that one I was converting the strings into lists, relatively the same though.

Cool, i always try and do these in one line with list comprehensions, i know its not in the 'pythonic' style but oh well :P

``````import random, string
print(''.join([random.choice(string.ascii_letters+"123456789") for f in range(8)]))``````

Imports dont count! :P
That is a great way to demonstrate the power of python, and show how useful list comprehensions can be.

I think that with this loop, you're trying to join the characters in the list 'shuffled'. This is more easily done with the statement

``rand = "".join(shuffled)``

Also, you should remove the 2 global declarations, which are useless. The best way to write python is to never use 'global'.

``````import random, string
print(''.join([random.choice(string.ascii_letters+"123456789") for f in range(8)]))``````

It's shorter, but the result is different: the letters and digits are not chosen with the same probability law. With your code, each letter or digit has the same probability to be chosen. AutoPython's method selects first the set of letters or the set of digits and then a random char in the chosen set. This increases the probability of digits because there are only 10 digits and 52 letters. The probability of a digit is about 5 times that of a letter. :)

commented: touche... I have a feeling that one line will be nigh impossible to do for that +4

I learn yet another useful function. But before I post the code. I need to say that, no, the first global statement was necessary, and when I removed it said "global name dig_let undefined". Of course that is when I attempted to use it outside the function. However, I do believe you could get around that by using the return function, however though, I do not know how to use that.
@gribulous
I never thought about probability, but as a result, I simply add 4 other digit variables. So now the probability difference is that less then 0.10
Here's what I got so far:

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

def randstr():

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def digit_letter():

global dig_let

dig_let = randint(1,2)

if dig_let == 1:
dig_let = digits,digits,digits,digits,digits
else:
dig_let = ascii_letters

shuffled = list("")
x = list(range(4))
for d in range(8):
digit_letter()
shuffled.append(choice(dig_let))

shuffle(shuffled)
count = ""

rand = "".join(shuffled)

print (rand)
input ()

randstr()``````

EDIT:

Woah, that just gives me a string of numbers.
This one should work:

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

def randstr():

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def digit_letter():

global dig_let

dig_let = randint(1,2)

if dig_let == 1:
str_dig = str(digits)
dig_combo = str_dig + str_dig + str_dig + str_dig + str_dig
dig_let = choice(dig_combo)
else:
dig_let = ascii_letters

shuffled = list("")
x = list(range(4))
for d in range(8):
digit_letter()
shuffled.append(choice(dig_let))

shuffle(shuffled)
count = ""

rand = "".join(shuffled)

print (rand)
input ()

randstr()``````

Yeah, now the program appears to be choosing a more variety of numbers where as before it picked various numbers multiple times in a row.

You could define

``alnum = ascii_letter + (digits * 5)``

at the top of your file, the remove the function digit_letter, and write

``````for d in range(8):
shuffled.append(choice(alnum))``````

also, you don't need `x=list(range(4))` .

I'm was already one step ahead of you. But it took a while. Here's what I have now.

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def randstr():

dig_let = str(digits)
dig_let = (dig_let * 5) + ascii_letters

shuffled = list("")
x = list(range(4))
for d in range(8):
shuffled.append(choice(dig_let))

shuffle(shuffled)

rand = "".join(shuffled)

print (rand)
input ()

randstr()``````

"digits" is already a string, it doesn't need to be converted. Now we can replace the middle block with

``shuffled = list(choice(dig_let) for d in range(8))``

Also, do we need to shuffle shuffled ?

I just became super efficient ;).
FROM:

``````from random import *

def randstr():

#Generates a random string.
#String consists of numbers 1-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#767,544,201,216 possible combinations

lower = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z")
upper = ("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z")

ch = randint(1,2)
if ch == 1:
case1 = lower
else:
case1 = upper

del ch

ch = randint(1,2)
if ch == 1:
case2 = lower
else:
case2 = upper

del ch

ch = randint(1,2)
if ch == 1:
case3 = lower
else:
case3 = upper

del ch

ch = randint(1,2)
if ch == 1:
case4 = lower
else:
case4 = upper

del ch

test1x = choice(case1)
test2x = choice(case2)
test3x = choice(case3)
test4x = choice(case4)
test1y = randint(1,9)
test2y = randint(1,9)
test3y = randint(1,9)
test4y = randint(1,9)
strconv1 = str(test1y)
strconv2 = str(test2y)
strconv3 = str(test3y)
strconv4 = str(test4y)
shuffled = [test1x, strconv1, test2x, strconv2, test3x, strconv3, test4x, strconv4]
shuffle(shuffled)
count = 0
for number in shuffled:

if count == 0:
sub_set = number
count = count+1

if count == 8:
rand = sub_set
quit

if count != 0:
if count != 8:
sub_set = sub_set+number
count = count+1

print (rand)
del test1x
del test2x
del test3x
del test4x
del test1y
del test2y
del test3y
del test4y
del strconv1
del strconv2
del strconv3
del strconv4
del shuffled
del count
del rand
del sub_set
del number
input ()

randstr()``````

TO:

``````from random import choice, randint, shuffle
from string import ascii_letters, digits

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def randstr():

dig_let = (digits * 5) + ascii_letters

shuffled = list(choice(dig_let) for d in range (8))

shuffle(shuffled)

rand = "".join(shuffled)

print (rand)
input ()

randstr()``````

THE POWER OF DANIWEB!

There is still place for improvement. Here is a new version

``````from random import choice
from string import ascii_letters, digits
dig_let = (digits * 5) + ascii_letters

#Generates a random string.
#String consists of numbers 0-9, letters a-z & A-Z.
#Letters and number can be in any order.
#Final generated number stored in "rand" variable.
#218,340,105,584,896 possible combinations!

def randstr(size):
return "".join(choice(dig_let) for d in range (size))

print(randstr(8))
input()``````

Wow, and I thought it couldn't get any better. But in this case would you have to use the variable size, or could use another variable like x or something.

Okay, now, seriously, you can't possibly make it shorter.