Search code examples
pythonscopeparameter-passinglocal

Having trouble figuring out params, arguments, passing variables to functions in Python


I understand this conceptually, but I can't seem to wrap my head around the syntax. Here is specifically what I'm working on - getting an average rating, from 5 inputs, and displaying an amount of stars as it relates to the average rating

def main():
    score = float(input("Enter a score between 0 and 10: "))

    while score < 0 or score > 10:
        score = float(input("ERROR! Enter a score between 0 and 10: "))
    else:
        for num in range(1,5):
            score = float(input("Enter a score between 0 and 10: "))
            avg = score / 5
        stars = determine_stars()
        print(f'Your score of {avg} gives you {stars}')
        
def determine_stars():
    if avg >= 9.0 or avg <= 10.0:
        stars = "*****"
    elif avg >= 8.0 or avg <= 8.9:
        stars = "****"
    elif avg >= 7.0 or avg <= 7.9:
        stars = "***"
    elif avg >= 6.0 or avg <= 6.9:
        stars = "**"
    elif avg >= 5.0 or avg <= 5.9:
        stars = "*"
    else:
        stars = "No Stars"

main()

Solution

  • Identifying bugs

    There are a few problems with the determine_stars() function:

    1. Scope of avg: It is a separate function from main() and therefore will not recognise the variable avg defined in the main() function. In other words, avg is outside the scope of determine_stars().

      Instead it should have its own parameter representing this value.

    2. Discrete ranges: The values of a float are essentially continuous, and so its decimal part can have as many digits as possible. So using discrete ranges will miss, for instance, values between 8.9 and 9.0 (such as 8.951).

      Instead, keep the ranges continuous.

    3. No output: Don't forget to specify the output value of the determine_stars() function using the return statement.

    4. If conditions: The conditions of the if statements should use and, not or. Every one of them would otherwise be True, resulting always in five stars.

    Also for the main() function:

    1. Validation: The while loop should be inside the for loop, to track every input entered by the user.

    2. Calculating average: The avg variable is not well defined. There needs to be a variable that can accumulate the scores, acting as the sum of all of them. It is this value that can then be divided to get the average.

    3. For loop range: The range(i, j) function iterates over numbers in the interval [i, j) (it is exclusive). Therefore range(1, 5) will only do 4 iterations rather than 5. Instead write range(0, 5) (or simply range(5)).

    Fixed code and annotation

    I have edited your code with fixes to these problems. To help you understand the syntax I have also added comments.

    # Outputs the star average from a given value.
    def determine_stars(avg):
        # Five stars: 9 <= avg <= 10
        if avg >= 9 and avg <= 10:
            stars = "*****"
            
        # Four stars: 8 <= avg < 9
        elif avg >= 8 and avg < 9:
            stars = "****"
            
        # Three stars: 7 <= avg < 8
        elif avg >= 7 and avg < 8:
            stars = "***"
            
        # Two stars: 6 <= avg < 7
        elif avg >= 6 and avg < 7:
            stars = "**"
            
        # One star: 5 <= avg < 6
        elif avg >= 5 and avg < 6:
            stars = "*"
            
        # Otherwise, no stars.
        else:
            stars = "No Stars"
        
        # Have the function produce the value of stars as its output
        return stars
    
    # Main program execution
    def main():
        
        # To store the sum of the user's scores.
        total = 0
    
        # Do 5 loops, to take 5 scores from the user.
        for num in range(0, 5):
            # Ask the user to input a score between 0 and 10. Convert their input to a float (i.e. a decimal).
            score = float(input("Enter a score between 0 and 10: "))
    
            # Validation: Keep rejecting their input until it is in the valid range (0 to 10).
            while score < 0 or score > 10:
                score = float(input("ERROR! Enter a score between 0 and 10: "))
            
            # Add the score to the total.
            total += score
        
        # Calculate the average score by dividing the total from the number of scores (5).
        avg = total / 5
        
        # Determine the star rating.
        stars = determine_stars(avg)
        
        # Output the star rating.
        print(f'Your score of {avg} gives you {stars}')