-1

I want to continue generating a single character at random as long as the loop condition is not met. I was hoping my code below will work but it doesn't:

import string
import random

def random_characters(number):
    i = 0
    new_string = ''

    while (i < number) :
        new_string = random.choice(string.ascii_lowercase)
        i = i + 1
        return new_string


random_characters(3)

When i run this code nothing happens and I don't get any feedback about any error. I may be using return new_string in a wrong way but I am unable to figure it out even if that is what I'm missing.

  • This may help: [What does `return` do? Nothing is ever returned](http://stackoverflow.com/questions/19066925/what-does-return-do-nothing-is-ever-returned) and BTW your `return` statement is not indented properly. – Ashwini Chaudhary Sep 28 '13 at 14:23

2 Answers2

3

Firstly, your return is inside the loop, so you don't ever loop several times. Change it to

def random_characters(number):
    i = 0
    new_string = ''

    while (i < number) :
        new_string = random.choice(string.ascii_lowercase)
        i = i + 1
    return new_string # <<< Dedent

random_characters(3)
#>>> 'c'

Then you need to actually build new_string, not just set it each time. Build a list and then "".join it:

def random_characters(number):
    i = 0
    letters = [] # Place to put the letters

    while (i < number) :
        letters.append(random.choice(string.ascii_lowercase)) # <<< Add the letter
        i = i + 1
    return "".join(letters) # <<< Join the letters into one string

random_characters(3)
#>>> 'lgp'

Then you should use for i in range(number) instead of the while loop:

def random_characters(number):
    letters = []

    for i in range(number): # <<< Deals with i for you.
        letters.append(random.choice(string.ascii_lowercase))

    return "".join(letters)

random_characters(3)
#>>> 'xay'

And you can use a shortened version with a list comprehension:

def random_characters(number):
    # MAGIC!
    letters = [random.choice(string.ascii_lowercase) for i in range(number)]

    return "".join(letters) # <<< Join the letters into one string

random_characters(3)
#>>> 'yby'

If you're wanting to run this, you have several choices. Either you can run this in the interactive interpreter:

%~> python -i random_characters.py
>>> random_characters(3)
'zgp'

or you can tell it to print the result inside the file:

print(random_characters(3))  # Python 3
print random_characters(3)   # Python 2
Veedrac
  • 58,273
  • 15
  • 112
  • 169
  • Just a note: there's a convention (or, well, it's commonplace) to use `_` as a loop variable if you're not going to use it. – Thomas Orozco Sep 28 '13 at 14:34
2

Two reasons:

  • You discard the characters you create (by reassigning to the same name)
  • You only return the first character anyway (by returning inside the loop)

Instead, consider doing:

import string
import random

def random_characters(number):
    i = 0
    random_chars = []

    while (i < number) :
        random_chars.append(random.choice(string.ascii_lowercase))  # Store the char you generate
        i = i + 1

    return ''.join(random_chars)  # Return once you have all the characters

Of course, that's not the most Pythonic way there is to do this. Here's a way that doesn't loop over an artificial condition:

def random_characters(number):
    return "".join((random.choice(string.ascii_lowercase) for _ in xrange(number)))

Note: this is called a generator expression

Thomas Orozco
  • 53,284
  • 11
  • 113
  • 116
  • This still didn't answer: **When I run this code nothing happens** – Ashwini Chaudhary Sep 28 '13 at 14:38
  • @hcwhsa You'll probably want to add a `print` statement in front of `random_characters(3)` if you want some output to appear: `print random_characters(3)`. Right now, you're generating the random string and throwing it away. – Thomas Orozco Sep 28 '13 at 14:38
  • That's what OP was asking for, and you didn't mention anything related to that in your answer. Even if they use your code they'll get no output. – Ashwini Chaudhary Sep 28 '13 at 14:41
  • @hcwhsa Sure, and? I'm sorry to break that to you, but the OP's code wasn't going to work anyway. Now you got two fixes when you only asked for one. – Thomas Orozco Sep 28 '13 at 14:42
  • @ThomasOrozco very true. The return statement was inside the loop and I had to bring it outside. Again true, I was generating random numbers and throwing them away hence I needed a 'print' statement to make sure that something actually *happens*. thanks – fromPythonImportNoob Sep 28 '13 at 15:30