0

I have a nested dictionary and instead of a hard coded query to query for ownername John I want to prompt the user for a name and just to test it, I type John upon being prompted and the program crashes with an error that says string indices must be integers.

The below works fine and returns Kitty.

John = { 1:  {'name': 'Kitty',  'kind':  'cat'},
         2:  {'name': 'Ruffle', 'kind':  'dog'},
         3:  {'name': 'Bobby',  'kind': 'fish'}
       }

petownername = John[1]['name']
print(petownername)

This also works fine when I hardcode the owner_name to John and I input the dictionary query with f string.

John = { 1:  {'name': 'Kitty',  'kind': 'cat'},
         2:  {'name': 'Ruffle', 'kind': 'dog'},
         3:  {'name': 'Bobby',  'kind': 'fish'}
       }

owner_name = John

petname   = f"{owner_name[1]['name']}"
print(petname)

But as mentioned above when I add new user input it stops working

John = { 1:  {'name': 'Kitty', 'kind': 'cat'},
         2:  {'name': 'Ruffle','kind': 'dog'},
         3:  {'name': 'Bobby',' kind': 'fish'}
       }

owner_name = str(input("Which pet owner do you want to look up?: "))


petname   = f"{owner_name[1]['name']}"
print(petname)

I am getting this error:

Which pet owner do you want to look up?: John
Traceback (most recent call last):
  File "test3.py", line 9, in <module>
    petname   = f"{owner_name[1]['name']}"
TypeError: string indices must be integers

So it works fine when I hardcode it and insert it via f string and input is clearly a string. Any idea why it's not working on user prompt? Do I need to store and refer back to the user prompt in another way perhaps?

dev
  • 651
  • 1
  • 6
  • 14
  • 3
    When you do `owner_name = John`, you are setting `owner_name` to a `dict` not a string. When you request the input from the user, now `owner_name` is the *string* `"John"`, not the `dict` you are trying to look into. – gen_Eric Jan 14 '20 at 17:14
  • 2
    Continuing off what @RocketHazmat said, you probably wanted another outer dictionary that maps the owner's name to their dictionary – sshashank124 Jan 14 '20 at 17:16
  • 1
    Also, why are you using "f-strings" here? You could just do `petname = owner_name[1]['name']`. – gen_Eric Jan 14 '20 at 17:18
  • I hardcoded it to find out if that f string will work. And I have proven that I can f string correctly with petname = f"{owner_name[1]['name']}" but why wouldn't it work with the user input? I want don't want to hardcode the user input since im planing to create more then one users. – dev Jan 14 '20 at 17:18
  • @dev Then consider @sshashank124's advice and create an outer dictionary holding all the users. Like: `users = {"John": {1: {'name': 'Kitty', 'kind': 'cat'}}}`. – gen_Eric Jan 14 '20 at 17:20

1 Answers1

2

It's not working because in the second snippet, owner_name is a dict, while in the third snippet it's a string -- specifically owner_name = 'John' so owner_name[1] == 'o', and 'o'['name'] raises that TypeError. The f-string is irrelevant.

To fix it, use one more level of nested dicts. See How do I create a variable number of variables?.

By the way, instead of a dict with ints as keys, you might want to use a list instead.

pet_owners = {
    "John": [
        {'name': 'Kitty', 'kind': 'cat'},
        {'name': 'Ruffle', 'kind': 'dog'},
        {'name': 'Bobby',' kind': 'fish'},
        ]
    }

owner_name = input('Pet owner name: ')

petname = pet_owners[owner_name][0]['name']  # Note the 0 instead of 1
print(petname)

Test run:

Pet owner name: John
Kitty

Also by the way, str(input()) is redundant in Python 3 since input() returns a string.

wjandrea
  • 28,235
  • 9
  • 60
  • 81