I was given the code that begins with the print_directory function and told not to alter anything below that. I've created the contact class above. Why am I receiving the attribute error, and how would I fix it? I'm trying to create a class that uses the variables in the main function to return the first name, last name, and phone numbers of the contacts list.
My code is below:
class Contact:
fname = ""
lname = ""
p_number = ""
def __init__(self,fname,lname,p_number):
self.fname = fname
self.lname = lname
self.p_number = p_number
def getfname(self):
return self.fname
def getlname(self):
return self.lname
def getp_number(self):
return self.p_number
def print_directory(contacts):
print("My Contacts")
print("-----------")
for person in contacts:
person.print_entry()
print("-----------\n")
# -----------------------------------------------------
def main():
champ = Contact("???", "Bobcat", "406-994-0000")
president = Contact("Waded", "Cruzado", "406-994-CATS")
professor = Contact("John", "Paxton", "406-994-4780")
contacts = [champ, president, professor]
print_directory(contacts)
champ.set_first_name("Champ")
president.set_title("President")
professor.set_title("Professor")
print_directory(contacts)
print("The area code for cell number", champ.get_cell_number(), "is", \
champ.get_area_code())
# -----------------------------------------------------
main()
CodePudding user response:
Hi it's seem that you trying to call a method that not exist for the "Contact" class.
person.print_entry()
the class Contact does not know to do with that call.
maybe you have to implement an print_entry() method in the class:
class Contact:
fname = ""
lname = ""
p_number = ""
def __init__(self,fname,lname,p_number):
self.fname = fname
self.lname = lname
self.p_number = p_number
def getfname(self):
return self.fname
def getlname(self):
return self.lname
def getp_number(self):
return self.p_number
def print_entry(self):
print(f" Name: {self.lname}, {self.fname}, Number: {self.p_number}")
CodePudding user response:
Your code will throw AttributeError: 'Contact' object has no attribute 'print_entry' because in your Contact class the method print_entry isn't defined.
Additionally you will also need to define set_first_name, and set_title in your Contact class or any lines where you call these class methods will throw a similar AttributeError.
You can add a definition for print_entry like this:
class Contact:
...
def print_entry(self):
# add your desired print statement here
...
Then use a similar structure to add your set_first_name and set_title methods. Something like this:
class Contact:
...
def set_first_name(self, fname):
self.fname = fname
...
However it is unclear which instance variable you want set_title to modify. You might consider adding another instance variable called title to your class.
CodePudding user response:
TL;DR: Define a method print_entry(self) that uses print to output as expected (this solution was already answered).
A more idiomatic, object-oriented and maintainable solution would be to use __str__ and print in two different levels (see below).
Background
Attribute Error explained
This is always a signal that your class or a third-party class is missing some attributes that you referenced, like accessed fields or invoked methods.
So you need to define it or if a third-party module used via import, you should check version-mismatches, etc.
Printing an object's representation
In almost every object-oriented programming-language there is a method that converts the object instance to a string representation. In Python this is either __repr__(self) or __str__(self) (similar like toString() in Java). These are standard methods (recognize by the surrounding double underscores __) that already exist and usually can be overridden.
Solution
Instead calling and defining print_entry instance-method, override the __str__ method like:
class Contact:
# omitted other to focus on string method
def __str__(self):
return "Name: " self.last_name ", " self.first_name;
and use it to print a Contact object instance person like:
print(person)
See also: How to print instances of a class using print()?
Benefits:
- this is an object-oriented pattern, reusing Python's standard
- keeping all
printstatements in one place (principle: abstraction-level, code-symmetry) like in your methodprint_directory - string-representation (
__str__) separated from UI/output-layer (print) so that they can be changed independently (principle: separation of concerns & single-responsibility)
Bonus
Tips:
- use an IDE like PyCharm (free community edition) or Eric, that will warn you in advance and offers quick-fix actions to add the missing attributes (methods, etc.).
- python naming convention for fields and methods is both lower snake-case, e.g.
first_name - setters need to be defined too, i.e.
set_first_name(self),set_title(self) - getters used for
get_cell_numberandget_area_codeare missing in class (whereas there is a fieldp_numberwith getter - meaningful names instead abbreviations usually pay-off in the long-run:
phone_numbercan be distinguished fromperson_number(some IDEs offer dictionary-assisted auto-completion and will pass spellchecking this way) - a pythonic way for string-interpolation using templates (since Python 3) are f-strings (see applied in Ulises answer)
