Continuing with our little database example, suppose that you found the friend database so useful at home, that you'd like to extend it into a database to keep track of business contacts. It would be very helpful to have a few additional fields in the database, let's say a company name and the type of product that the company produces. Following the example of the Friend object, we could create a Contact object as follows:
class Contact:
def __init__(self,name,company,phone='',email='',product=''):
self.name = name
self.company = company
self.phone = phone
self.email = email
self.product = product
def __str__(self):
return 'Name: %s\nCompany: %s\nPhone: %s\nEmail: %s\nProduct: %s' % \
(self.name,self.company,self.phone,self.email,self.product)
def __repr__(self):
return self.__str__()
Now we'd like to create an object that would let us store, add and search a
database of contacts. The details of opening files, pickling, searching, and indexing
really haven't changed - our Contactdb object can simply inherit all of them
from the Frienddb object. The only real change is that now we'll be storing
Contact objects in the list called db inside of the object instead of
Friend objects, so we'll need to overwrite the add method:
from frienddb import Frienddb
class Contactdb(Frienddb):
def add(self,name,company,phone='',email='',product=''):
self.db.append(Contact(name,company,phone,email,product))
By putting the name of another class (Frienddb) in parentheses after
the name of our new class (Contactdb) we're informing Python that this class will
inherit methods and attributes from that old class. If we invoke a method or try to
access an attribute that's been
explicitly defined for our new class, Python will use the one we've defined. But if we
refer to a method or attribute we haven't explicitly defined, it will refer to that method
or attribute in the
so-called ``parent'' class. (Python even supports multiple inheritance; if you have a
comma-separated list of classes in parentheses after your class name, python will search
each of them in turn for methods or attributes not explicitly defined for the new class.)
Thus after simply defining the add method, we can create and use our contact
database:
>>> import contactdb
>>> fdb.search('harry')
[Name: Harry Smith
Phone: 443-2199
Email: hsmith@notmail.com]
>>> cdb = contactdb.Contactdb('new.db')
>>> cdb.add('Mary Wilson','Brainpower, Inc.','222-3292',
... 'mw@brainpower.net','consulting')
>>> cdb.add('John Jenkins','Advanced Microstuff','321-9942',
... 'jjenkins@advmicro.com','disk drives')
>>> cdb.add('Fred Smith','Hitech Storage','332-1994',
... 'fredsmith@hitechstorage.com','magnetic tape')
>>> cdb.add('Al Watson',"Brains 'r Us",'335-2324',
... 'al@brains.net','consulting')
>>> cdb.search('mary')
[Name: Mary Wilson
Company: Brainpower, Inc.
Phone: 222-3292
Email: mw@brainpower.net
Product: consulting]
>>> cdb[3]
Name: Al Watson
Company: Brains 'r Us
Phone: 335-2324
Email: al@brains.net
Product: consulting
>>> cdb['John Jenkins']
Name: John Jenkins
Company: Advanced Microstuff
Phone: 321-9942
Email: jjenkins@advmicro.com
Product: disk drives
All of the methods we implemented for the Frienddb class work correctly
with our new class. Since we defined a Contact object, and explicitly defined
an add method to use it, Python knows how to display the contacts properly.
Now suppose that we want to expand the search method to allow us to specify, using a keyword argument, whether we wish to search the database for a name, a company or a product. We've already developed a method to search for names when we wrote the Frienddb class, so we can use that when we're searching for names, and add additional code to handle the other cases. When you need to access a method from another class, you need to treat the method like a regular function. In other words, instead of following self with the method name, you call the function with self as the first argument to the method, as illustrated below when the search method from the Frienddb class is invoked in our new search method:
def search(self,name='',company='',product=''):
results = []
if name:
found = Frienddb.search(self,name)
results.extend(found)
if company:
srch = re.compile(company,re.I)
found = []
for item in self.db:
if srch.search(item.company):
found.append(item)
results.extend(found)
if product:
srch = re.compile(product,re.I)
found = []
for item in self.db:
if srch.search(item.product):
found.append(item)
results.extend(found)
return results
(As in previous examples, this method would only make sense if it was part of the
definition for the class Contactdb.) Now we can search for either names,
companies or products:
>>> cdb = contactdb.Contactdb('new.db')
>>> found = cdb.search(product='consult')
>>> for i in found:
... print '-' * 10
... print i
...
----------
Name: Mary Wilson
Company: Brainpower, Inc.
Phone: 222-3292
Email: mw@brainpower.net
Product: consulting
----------
Name: Al Watson
Company: Brains 'r Us
Phone: 335-2324
Email: al@brains.net
Product: consulting
>>> found = cdb.search(name='mary')
>>> print found[0]
Name: Mary Wilson
Company: Brainpower, Inc.
Phone: 222-3292
Email: mw@brainpower.net
Product: consulting