3
\$\begingroup\$

I'm working on some code examples in 'Automate the boring stuff in python...' to prepare for my first year of CS. I want to know if its better to use an array with random selection below or rather multiple if/elif conditionals to generate output. Any and all suggestions are welcome.

import sys
import random
import time

answer = ['It is certain', 'It is so', 'Try later', 'Ask Again', 'Not good', 'Doubtful']
r = random.randint(0,5)

def getAnswer():
    print (answer[r])

def Main():
    try = input('Try your luck. Yes or no.\n')
    if try == 'yes':
        getAnswer()
        sys.exit()
    else:
        print('May luck be on your side.')
        sys.exit()

if __name__ == '__main__':
    Main()
\$\endgroup\$
4
\$\begingroup\$

The array is clean and easy to read, and it takes up much less space than an army of if/elif/else statements. In my opinion, what you have is much better than the alternative.

That said, there are a couple of things that could be changed.

First, either move the random selection into the getAnswer() function, or change the function to accept an argument. What if you decide later on that you want to get multiple answers? Even if you only call getAnswer() once, making one of these changes will make the function's job clearer.

Second, remove the hard-coded array length in the random.randint() arguments. If you later add or remove answers, the arguments to randint() need to be changed, too. This can be avoided by either using random.choice() (ideal if getAnswer() doesn't take any arguments) or by using random.randint(0, len(answer) - 1) or random.randrange(len(answer)).

randrange() is typically preferred over randint(). Everything else in Python treats ranges as including the start index and excluding the end index, but randint() includes the end index. Not only does that make randint() inconsistent with everything else, but it also makes working with lists and sequences more error-prone (notice how clean and neat randrange(len(my_list)) is compared to randint(0, len(my_list) - 1)?).

Here is how these changes might look (along with one or two other changes, unrelated to how the random selection is made).

Option 1: Random selection inside of getAnswer():

import sys
import random
import time

ANSWERS = ['It is certain', 'It is so', 'Try later', 'Ask Again', 'Not good', 'Doubtful']

def getAnswer():
    print (random.choice(ANSWERS))

def Main():
    prompt_string = 'Try your luck. Yes or no.\n'
    while input(prompt_string).strip().lower() in ('yes', 'y')
        prompt_string = 'Try again (yes or no)?\n'
        getAnswer()

    print('May luck be on your side.')
    sys.exit()

if __name__ == '__main__':
    Main()

Option 2: getAnswer() takes an argument

import sys
import random
import time

ANSWERS = ['It is certain', 'It is so', 'Try later', 'Ask Again', 'Not good', 'Doubtful']

def getAnswer(chosen_index):
    print (ANSWERS[chosen_index])

def Main():
    prompt_string = 'Try your luck. Yes or no.\n'
    while input(prompt_string).strip().lower() in ('yes', 'y')
        prompt_string = 'Try again (yes or no)?\n'
        getAnswer(random.randrange(len(ANSWERS)))

    print('May luck be on your side.')
    sys.exit()

if __name__ == '__main__':
    Main()
\$\endgroup\$
  • \$\begingroup\$ Thanks, these are great suggestions to further clean up my code and learn some good programming practices. \$\endgroup\$ – Zakar H. Aug 12 '15 at 3:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.