IndexError: list index out of range shows up when the value specified is inside the range of the list

Viewed 46

I get "IndexError: list index out of range" when I try to run this, even though the random choice made is within the list range. I want the computer to make a choice and perform a set of action that I have made. I can't seem to identify the issue in this code. I've inserted the code down below.(also I did import random)

def do_question():
  questions = ["What is your favourite movie?", "What is your name?", "What are your hobbies?"]
  q_choice = random.choice(questions)

  if q_choice == questions[0]:
    inter = input(f"{q_choice}")
    questions.remove(q_choice)
    
    print("Amazing! My favourite movie is Pirates Of The Caribbean: The Curse Of The Black Pearl")

  if q_choice == questions[1]:
    inter = input(f"{q_choice}")
    questions.remove(q_choice)
    
    print(f"Glad to talk to you, {inter}. I'm PYchatter.")

  if q_choice == questions[2]:
    inter = input(f"{q_choice}")
    questions.remove(q_choice)
    
    print("Wow! Those are nice hobbies you have. My hobby is talking to people like I am doing right now.")
2 Answers

You are calling questions.remove then at next if statement questions array items. In sample code you have given you initialize list with 3 items, consider first if statement is true so you remove one item from list that results in array with 2 items, then at third if statement you are checking equality with third item that does not exist so far and throws exception.

One solution is using if-else statement.

What's happening here as @Eskandar answer explained, is that you're changing the length of the list and then trying to access it again as if it had the same length.

Consider this:

l = [1, 2, 3]
choice = random.choice(l) # Let's say that the choice is 2

if choice == l[0]: # Skipped
    print("Choice was 1")
    l.remove(choice)

if choice == l[1]:
    print("Choice was 2")
    l.remove(choice) # Since choice was 2, now the list l is [1, 3]

if choice == l[2]: # But there are only 2 elements in l!!!
    ...

A better way to do what you're trying to do could be:

import random

qa_map = {
        "What is your favourite movie?": "Amazing! My favourite movie is Pirates Of The Caribbean: The Curse Of The Black Pearl",
        "What is your name?": "Glad to talk to you, {}. I'm PYchatter.",
        "What are your hobbies?": "Wow! Those are nice hobbies you have. My hobby is talking to people like I am doing right now.",
    }

def do_question() -> None:
    q_choice = random.choice(list(qa_map.keys())) # Choose a random question
    answer = input(q_choice) # Ask the question
    
    # Get the answer from the map and format it. If the reply doesn't have any
    # formatting, it won't do anything, which is what we want.
    reply = qa_map[q_choice].format(answer)
    print(reply)

    # Remove the question from the map so it can't be asked again
    del qa_map[q_choice]

Now if I do do_question() three times and the input I give is always "apples" I get:

Amazing! My favourite movie is Pirates Of The Caribbean: The Curse Of The Black Pearl
Glad to talk to you, apples. I'm PYchatter.
Wow! Those are nice hobbies you have. My hobby is talking to people like I am doing right now

.

Related