A First Example of Class Instances#
We have used many built-in types and library classes. Now we define our own. As a first example, a contact has a name, phone number, and email address — three pieces of data that belong together as one entity.
Defining the Class#
class Contact:
def __init__(self, name: str, phone: str, email: str):
self.name = name
self.phone = phone
self.email = email
class Contact:declares a new type namedContact.__init__is the initialiser — Python calls it automatically when a new object is created.selfis the first parameter of every instance method. It refers to the specific object being created or operated on. You never pass it explicitly; Python fills it in.self.name = namestores the argument in an instance variable — data that lives as long as the object exists.
Creating Instances#
c = Contact("Marie Ortiz", "773-508-7890", "mortiz2@luc.edu")
This creates a new Contact object and binds it to c. Each object
has its own copy of the instance variables.
Accessing Instance Variables#
Run this to create a Contact and read back each of its instance
variables — try changing the values:
>>> class Contact:
... def __init__(self, name: str, phone: str, email: str):
... self.name = name
... self.phone = phone
... self.email = email
...
>>> c = Contact("Marie Ortiz", "773-508-7890", "mortiz2@luc.edu")
>>> print(c.name)
Marie Ortiz
>>> print(c.phone)
773-508-7890
>>> print(c.email)
mortiz2@luc.edu
Adding a __str__ Method#
__str__ is called automatically whenever Python needs a string
representation of the object (e.g., inside print()):
class Contact:
def __init__(self, name: str, phone: str, email: str):
self.name = name
self.phone = phone
self.email = email
def __str__(self) -> str:
return (f"Name: {self.name}\n"
f"Phone: {self.phone}\n"
f"Email: {self.email}")
def set_email(self, new_email: str) -> None:
self.email = new_email
Run this version, which defines the class with __str__ and then prints
an instance:
>>> class Contact:
... def __init__(self, name: str, phone: str, email: str):
... self.name = name
... self.phone = phone
... self.email = email
... def __str__(self) -> str:
... return (f"Name: {self.name}\n"
... f"Phone: {self.phone}\n"
... f"Email: {self.email}")
...
>>> c = Contact("Marie Ortiz", "773-508-7890", "mortiz2@luc.edu")
>>> print(c)
Name: Marie Ortiz
Phone: 773-508-7890
Email: mortiz2@luc.edu
Adding Methods#
Instance methods work exactly like functions, but receive self as
their first argument. We can add a method to update the email address:
def set_email(self, new_email: str) -> None:
self.email = new_email
Run this to call the method and confirm the email address changed:
>>> class Contact:
... def __init__(self, name: str, phone: str, email: str):
... self.name = name
... self.phone = phone
... self.email = email
... def set_email(self, new_email: str) -> None:
... self.email = new_email
...
>>> c = Contact("Marie Ortiz", "773-508-7890", "mortiz2@luc.edu")
>>> c.set_email("maria.ortiz@gmail.com")
>>> print(c.email)
maria.ortiz@gmail.com
Privacy by Convention#
Python has no private keyword. The convention is to prefix an
attribute with a single underscore (_name) to signal that it is
intended for internal use and should not be accessed directly from
outside the class. Double underscore (__name) invokes name
mangling, which makes accidental access harder.
For the Contact class this is a matter of taste; we leave the attributes public since this is a simple data container.
Using a List of Contacts#
contacts = [
Contact("Marie Ortiz", "773-508-7890", "mortiz2@luc.edu"),
Contact("Otto Heinz", "773-508-9999", "oheinz@luc.edu"),
]
for contact in contacts:
print(contact)
print()