To me it doesn't make any sense to have a Contact object also own a contact_list attribute, and even less if it's class-wide instead of instanced. I would do this instead:
class Contact(object):
def __init__(self, name, email):
self.name = name
self.email = email
def __str__(self):
return f"{self.name} <{self.email}>"
# or "{} <{}>".format(self.name, self.email) in older versions of
# python that don't include formatted strings
contacts = []
def print_contacts(contacts: "list of contacts") -> None:
for c in contacts:
print(c)
adam = Contact("Adam Smith", "adam@email.com")
contacts.append(adam)
bob = Contact("Bob Jones", "bob@email.com")
contacts.append(bob)
charlie = Contact("Charlie Doe", "charlie@email.com")
contacts.append(charlie)
print_contacts(contacts)
# Adam Smith <adam@email.com>
# Bob Jones <bob@email.com>
# Charlie Doe <charlie@email.com>
Or alternatively, model an AddressBook that knows how to create Contact objects and display them all.
class AddressBook(list):
def add_contact(self, *args, **kwargs):
new_contact = Contact(*args, **kwargs)
self.append(new_contact)
def display_contacts(self):
for contact in self:
print(contact)
contacts = AddressBook()
contacts.add_contact("Adam Smith", "adam@email.com")
contacts.add_contact("Bob Jones", "bob@email.com")
contacts.add_contact("Charlie Doe", "charlie@email.com")
contacts.display_contacts()