0

When I run the code as below, it returns attribute error.

AttributeError: 'Contact' object has no attribute 'find_info'

How should I fix this??

phonebook = {}
Contact = namedtuple('Contact', ['phone', 'email', 'address'])

def add_contact(phonebook):
    name = input()
    phone = input()
    email = input()
    address = input()
    phonebook[name] = Contact(phone, email, address)
    print('Contact {} with phone {}, email {}, and address {} has been added successfully!' .format(name, phonebook[name].phone, phonebook[name].email, phonebook[name].address))
    num = 0
    for i in phonebook.keys():
        if i in phonebook.keys():
            num += 1
    print('You now have', num, 'contact(s) in your phonebook.')
def consult_contact(phonebook):
    find_name = input('What is the name of the contact?\n')
    find_info = input('What information do you need?\n')
    if find_name not in phonebook:
        print('Contact not found!')
    else:
        print(phonebook[find_name].find_info)

if __name__ == "__main__":
    add_contact(phonebook)
    consult_contact(phonebook)



Alex Hu
  • 37
  • 7
  • `print(phonebook[find_name].find_info)` - the error message would have included relevant line. If such a line (the only usage of `find_info` as a property as well) is presumed to be valid, remove all non-related code and provide a minimal example case. If the question is about "How can I access a NamedTuple property from a string?", again, remove all non-related code and focus on the specific issue. – user2864740 May 20 '20 at 18:08
  • Issue resolved by including import statement. from collections import namedtuple – Rima May 20 '20 at 18:12
  • That seems suspect. Without having such in scope, `namedtuple` itself would have resulted in an error. – user2864740 May 20 '20 at 18:14

4 Answers4

2

Your problem is that you're treating find_info as an attribute in consult_phonebook.

Try this:

def consult_contact(phonebook):
    find_name = input('What is the name of the contact?\n')
    find_info = input('What information do you need?\n')
    if find_name not in phonebook:
        print('Contact not found!')
    else:
        print(getattr(phonebook[find_name], find_info))

When using getattr(phonebook[find_name], find_info) you're essentially fetching the attribute stored in find_info from your contact.

S.D.
  • 2,486
  • 1
  • 16
  • 23
1

You can use getattr(phonebook[find_name], find_info). Or perhaps change your Contact object to be a dictionary so you can use find_info as an index directly. You can look into some kind of "AttrDict" if you want both attribute and variable key access: Accessing dict keys like an attribute?

Alex
  • 947
  • 6
  • 16
  • Thank you for answering. I've been studying python for only weeks, what does getattr() do? – Alex Hu May 20 '20 at 18:13
  • getattr() lets you access an attribute of an object when you have its name in a variable. Check out https://docs.python.org/3/library/functions.html#getattr and also look at sister method `setattr`. In your case, you have the info in a variable called `find_info`, and the value should be one of `phone`, `email`, or `address` (otherwise getattr will likely fail). Good luck with Python! – Alex May 20 '20 at 18:17
1

You cant use the dot notation to access the tuple's attributes like that. The code ends up looking for a method called 'find_info', which doesn't exist.

You can use :

getattr(phonebook[find_name], find_info)

To get the attribute held by the find_info variable.

SimonR
  • 1,774
  • 1
  • 4
  • 10
0

In your code the value type of find_info is string.