1
\$\begingroup\$

I have a function returns a random integer number. This function only accepts these three numbers 1,2 and 3(there's another function in my code which is make sure of this otherwise that function will raise ValueError and re-prompt the user again). If the function gets 1 it should generate a random number between 0-9. If gets 2 it should generate a random number between 10-99. And lastly, if gets 3 it should generate a number between 100-999. I'm wondering if there is a way in which I don't use all these ifs.

My code for now:

from random import randrange

def generate_integer(level):
    if level == 1:
       N = randrange(0,10)
    elif level ==2:
       N = randrange(10,100)
    else:
       N = randrange(100,1000)
    return N
\$\endgroup\$
3
  • \$\begingroup\$ Your code does not do what you say it does. Check your ranges. \$\endgroup\$
    – Reinderien
    May 5, 2022 at 3:07
  • \$\begingroup\$ Oh, I have edited my question again. The range for 2 is between 10-99. And for 3 is between 100-999 \$\endgroup\$
    – Ahmed
    May 5, 2022 at 3:15
  • 2
    \$\begingroup\$ (Mention (not least in the source code) whether the upper bound is to be exclusive or inclusive.) \$\endgroup\$
    – greybeard
    May 5, 2022 at 5:39

2 Answers 2

2
\$\begingroup\$

An issue I see with this code is that it behaves unexpectedly if passed another value than 1, 2 or 3: it silently accepts any value and assumes anything other than 1 and 2 is 3, which is not what is specified in your description of the code.

Invalid/out of range inputs should cause the function to raise an exception.

Furthermore, the function should be documented (using a docstring) to indicate what values are accepted. Using python type hints to specify what type of input and output the caller should provide/expect can also be useful.

Finally, the logic can be improved by using a lookup table.

def generate_integer(level: int) -> int:
    """Return a random integer in a range specified by the `level` argument:
    
    level = 1: [0,9]
    level = 2: [10,99]
    level = 3: [100,999]"""
    
    bounds = [0, 10, 100, 1000]
    return randrange(bounds[level-1], bounds[level])

This code will raise a TypeError or IndexError if called with an invalid value. You could add your own checks for type and range of the argument in order to have more descriptive error messages, but in a simple case like this it might not be necessary.

\$\endgroup\$
1
\$\begingroup\$
>>> 10**1
10
>>> 10**2
100
>>> 10**3
1000

So you can do randrange(10**(level - 1), 10**level) for a similar solution (level 1 results in a range (1, 10) rather than (0, 10)).

\$\endgroup\$
4
  • \$\begingroup\$ I have tried to do so. But as you mentioned the number zero is not included. I need to include the number 0. \$\endgroup\$
    – Ahmed
    May 5, 2022 at 3:17
  • \$\begingroup\$ randrange([0, 0, 10, 100][level], 10**level) \$\endgroup\$
    – greybeard
    May 5, 2022 at 5:36
  • \$\begingroup\$ Great answer. But what is the purpose of the first 0 in the list? \$\endgroup\$
    – Ahmed
    May 5, 2022 at 5:47
  • \$\begingroup\$ @Ahmed Symmetry. \$\endgroup\$
    – l0b0
    May 5, 2022 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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