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.

Recommended Answers

All 18 Replies

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)

instead of

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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.