
Extending built-ins
One of the most interesting uses of this kind of inheritance is adding functionality to built-in classes. In the Contact
class seen earlier, we are adding contacts to a list of all contacts. What if we also wanted to search that list by name? Well, we could add a method on the Contact
class to search it, but it feels like this method actually belongs on the list itself. We can do this using inheritance:
class ContactList(list): def search(self, name): '''Return all contacts that contain the search value in their name.''' matching_contacts = [] for contact in self: if name in contact.name: matching_contacts.append(contact) return matching_contacts class Contact: all_contacts = ContactList() def __init__(self, name, email): self.name = name self.email = email self.all_contacts.append(self)
Instead of instantiating a normal list as our class variable, we create a new ContactList
class that extends the built-in list
. Then we instantiate this subclass as our all_contacts
list. We can test the new search functionality as follows:
>>> c1 = Contact("John A", "johna@example.net") >>> c2 = Contact("John B", "johnb@example.net") >>> c3 = Contact("Jenna C", "jennac@example.net") >>> [c.name for c in Contact.all_contacts.search('John')] ['John A', 'John B'] >>>
Are you wondering how we changed the built-in syntax []
into something we can inherit from? Creating an empty list with []
is actually a shorthand for creating an empty list using list()
; the two syntaxes are identical:
>>> [] == list() True
So, the list
data type is like a class that we can extend, not unlike object
.
As a second example, we can extend the dict
class, which is the long way of creating a dictionary (the {:}
syntax).
class LongNameDict(dict): def longest_key(self): longest = None for key in self: if not longest or len(key) > len(longest): longest = key return longest
This is easy to test in the interactive interpreter:
>>> longkeys = LongNameDict() >>> longkeys['hello'] = 1 >>> longkeys['longest yet'] = 5 >>> longkeys['hello2'] = 'world' >>> longkeys.longest_key() 'longest yet'
Most built-in types can be similarly extended. Commonly extended built-ins are object
, list
, set
, dict
, file
, and str
. Numerical types such as int
and float
are also occasionally inherited from.