Skip to content

Instantly share code, notes, and snippets.

@insipx
Created December 28, 2014 13:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save insipx/0e28a0ee318f40e15182 to your computer and use it in GitHub Desktop.
Save insipx/0e28a0ee318f40e15182 to your computer and use it in GitHub Desktop.
import random
def genName():
boyNames = {0: "Jack",1: "Andrew", 2: "Mike",3: "Terry",4: "Torvald", 5: "Gatsby"}
girlNames = {0: "Alice", 1: "Hana", 2: "Clare", 3: "Janet", 4: "Daisy"}
genderList = {0: "M", 1: "F"}
randGender = random.randrange(0, 2)
randGirlName = random.randrange(0, len(girlNames))
randBoyName = random.randrange(0, len(boyNames))
askGender = raw_input("What Name Gender would you like? (m/f) (enter 'r' for random)")
askGender = askGender.lower()
if askGender != "m":
if askGender != "r":
if askGender !="f":
print "please enter 'M' ,'F', or 'R' to initiate the Random Name Generator"
if askGender == "r":
if genderList[randGender] == "m":
return boyNames[randBoyName]
else:
return girlNames[randGirlName]
if askGender == "m":
return boyNames[randBoyName]
elif askGender == "f":
return girlNames[randGirlName]
print "Welcome to the Simple Random Name Generator by Liquid Think!"
print genName()
@johnzeringue
Copy link

Found you through /r/dailyprogrammer. Here's my feedback on your code:


As a programmer at any skill level, you should always be working to make your code more readable, maintainable, and testable. In this case, you'd benefit tremendously from introducing a few new functions in order to either (1) reduce code duplication or (2) improve readability/maintainability.

Starting with #1, it immediately struck me that you're writing the same code for sampling a random entry from a dictionary three times. Let's write a new function to do this instead:

import random

def sample(dictionary):
    # the first argument can be omitted as it defaults to 0
    randomIndex = random.randrange(len(dictionary))
    return dictionary[randomIndex]

You can see the revised code here.

Next, we'll try and improve readability. Currently, in genName, you're doing two things: prompting the user for input and then generating the name. You should move the user interaction to its own function, like this:

def promptForGender():
    genderList = {0: "male", 1: "female"}

    response = raw_input("What Name Gender would you like? (m/f) (enter 'r' for random)")
    response = response.lower()

    # convert user input into some sort of normalized gender format
    # this could stay "m" and "f" instead
    if response == "m":
        return "male"
    elif response == "f":
        return "female"
    elif response == "r":
        return sample(genderList)
    else:
        print "please enter 'M' ,'F', or 'R' to initiate the Random Name Generator"

Look here for the full code up to this point.

Finally, just a note about your use of dictionaries. In modern programming languages, you're typically provided at least two types of "one-dimensional" data structures: dictionaries (also known as maps or hashes) and lists (AKA vectors or arrays). Because they're almost always present and incredibly useful, it's important to know the difference.

Without going into any one languages implementation details, you will want to use dictionaries when you have keys that are non-integers, negative, or non-sequential and use lists in all other instances. In this case, your keys are from 0 to length - 1, so you should be using lists instead of dictionaries.

In your code, that means we'll go from this:

boyNames = {0: "Jack",1: "Andrew", 2: "Mike",3: "Terry",4: "Torvald", 5: "Gatsby"}

to this:

boyNames = ["Jack", "Andrew", "Mike", "Terry", "Torvald", "Gatsby"]

Because you were using dictionaries as if they were lists before, you can access elements with exactly the same syntax (boyNames[1]).

After these three revisions, my version of your code looks like this:

import random

def sample(items):
    # the first argument can be omitted as it defaults to 0
    randomIndex = random.randrange(len(items))
    return items[randomIndex]

def promptForGender():
    genderList = ["male", "female"]

    response = raw_input("What Name Gender would you like? (m/f) (enter 'r' for random)")
    response = response.lower()

    # convert user input into some sort of normalized gender format
    # this could stay "m" and "f" instead
    if response == "m":
        return "male"
    elif response == "f":
        return "female"
    elif response == "r":
        return sample(genderList)
    else:
        print "please enter 'M' ,'F', or 'R' to initiate the Random Name Generator"

def genName():
    boyNames = ["Jack", "Andrew", "Mike", "Terry", "Torvald", "Gatsby"]
    girlNames = ["Alice", "Hana", "Clare", "Janet", "Daisy"]

    gender = promptForGender()

    if gender == "male":
        return sample(boyNames)
    elif gender == "female":
        return sample(girlNames)

print "Welcome to the Simple Random Name Generator by Liquid Think!"
print genName()

So let's see what we've done. Is the code any shorter? No. Does it do anything new? Nope. So what exactly did all of this accomplish?

First, this new version of your program is more readable. Notice that we no longer have any nested if-statements and that the names of the functions we added provide clues for what their code does. At a high-level, it's now obvious what genName is supposed to do, even without comments. If you reread this code in a month or share it with a friend, it'll still be clear what's going on.

Second, it's now much easier to modify the code. Consider changing the way input is taken. Now, we could easily add new keywords like this (inside promptForGender):

    if response in ["m", "male", "boy"]:
        return "male"
    elif response in ["f", "female", "girl"]:
        return "female"
    elif response in ["r", "random"]:
        return sample(genderList)

Each new keyword only has to be added in one place and because we've separated different parts of the program, there's no danger of this modification breaking other parts of the code.

So, in a way not visible to the user, we've made substantial improvements to the code. This is a process known as refactoring.

Hope you find this helpful. Good luck with your challenge!

@insipx
Copy link
Author

insipx commented Dec 30, 2014

This is great! Thanks for all the help--This is only the first challenge and I'm already learning more than I had hoped!

I'll make sure to update the post on my website, and keep in mind your suggestions for the future challenges.
Thanks Again!

@mossbanay
Copy link

Rather than bothering with selecting an element by a random index from random.randrange, you can use random.choice(), for example:

if gender == "male":
    return random.choice(boyNames)
elif gender == "female":
    return random.choice(girlNames)

That omits the sample method johnzeringue mentioned above and arguably adds to the readability of the code.
Hope I could help!

@johnzeringue
Copy link

leaen, I knew about about random.choice at the time of writing but wanted to keep my post about coding instead of Python libraries.

Thanks for adding that, though. It's good to know what's already been written for you when you progress to larger projects.

@insipx
Copy link
Author

insipx commented Jan 31, 2015

Thank all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment