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
print
statements 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_number
andget_area_code
are missing in class (whereas there is a fieldp_number
with getter - meaningful names instead abbreviations usually pay-off in the long-run:
phone_number
can 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)