pythonlisttypeerror

TypeError: There are no type variables left in list[...]


How the game works is that there is a 3-digit number, and you have to guess it. If you guess a digit in the right spot, you get a strike, and if you guess a digit but in the wrong spot you get a ball. I've coded it like this:

import random
x = random.randint(1, 9) 
y = random.randint(1, 9)
z = random.randint(1, 9)
userguessunlisted = input('What number do you want to guess?')
numbertoguess = list[x, y, z] 

userguess = list(userguessunlisted)
b = 0
s = 0
while 0 == 0:
    if userguess[0] == numbertoguess[0]:
        s = s + 1
    if userguess[0] == numbertoguess[1]:
        b = b + 1
    if userguess[0] == numbertoguess[2]:
        b = b + 1
    if userguess[1] == numbertoguess[0]:
        b = b + 1
    if userguess[1] == numbertoguess[1]:
        s = s + 1
    if userguess[1] == numbertoguess[2]:
        b = b + 1
    if userguess[2] == numbertoguess[0]:
        b = b + 1
    if userguess[2] == numbertoguess[1]:
        b = b + 1
    if userguess[2] == numbertoguess[2]:
        s = s + 1
    print(s + "S", b + "B")
    if s != 3:
        b = 0
        s = 0
    else:
        print('you win!')
        break

Solution

  • When you said list[x, y, z] on line 5, you used square brackets, which python interprets to be a type annotation. For example, if I wanted to specify that a variable is a list of ints, I could say

    my_list_of_ints: list[int] = [1, 2, 3]
    

    I think what you meant to do is create a new list from x, y, and z. One way to do this is

    numbertoguess = list([x, y, z])
    

    which is probably what you meant to write. This is valid because the list function takes an iterable as its one and only argument.

    However, the list portion is redundant; square brackets on the right-hand side of an assignment statement already means "create a list with this content," so instead you should simply say

    numbertoguess = [x, y, z]
    

    A few other notes:

    1. input will return a string, but you are comparing that string to integers further down, so none of the comparisons will ever be true. What you want to say is something like the following:

      while True:
          try:
              userguessunlisted = int(input('What number do you want to guess?'))
          except:
              continue
          break
      

      What this code does is attempts to parse the string returned from input into an int. If it fails to do so, which would happen if the user inputted something other than a valid integer, an exception would be thrown, and the except block would be entered. continue means go to the top of the loop, so the input line runs repeatedly until a valid int is entered. When that happens, the except block is skipped, so break runs, which means "exit the loop."

    2. userguessunlisted is only ever going to contain 1 number as written, so userguess will be a list of length 1, and all of the comparisons using userguess[1] and userguess[2] will throw an IndexError. Try to figure out how to wrap the code from (1) in another loop to gather multiple guesses from the user. Hint: use a for loop with range.

      It might also be that you meant for the user to input a 3-digit number all at once. In that case, you can use a list comprehension to grab each character from the input and parse it into a separate int. This is probably a bit complicated for a beginner, so I'll help you out:

      [int(char) for char in input('What number do you want to guess?')]
      
    3. print(s + "S", b + "B") will throw TypeError: unsupported operand type(s) for +: 'int' and 'str'. There are lots of ways to combine non-string types with strings, but the most modern way is using f-strings. For example, to combine s with "S", you can say f"{s}S".

    4. When adding some amount to a variable, instead of saying e.g. b = b + 1, you can use the += operator to more concisely say b += 1.

    5. It's idiomatic in python to use snake_case for variables and Pascal case for classes. So instead of writing e.g. numbertoguess, you should use number_to_guess. This makes your code more readable and familiar to other python programmers.

    Happy coding!