Online Book Reader

Home Category

Learning Python - Mark Lutz [406]

By Root 1692 0
resources for more on this topic.

* * *

Why You Will Care: Classes and Persistence


I’ve mentioned Python’s pickle and shelve object persistence support a few times in this part of the book because it works especially well with class instances. In fact, these tools are often compelling enough to motivate the use of classes in general—by picking or shelving a class instance, we get data storage that contains both data and logic combined.

For example, besides allowing us to simulate real-world interactions, the pizza shop classes developed in this chapter could also be used as the basis of a persistent restaurant database. Instances of classes can be stored away on disk in a single step using Python’s pickle or shelve modules. We used shelves to store instances of classes in the OOP tutorial in Chapter 27, but the object pickling interface is remarkably easy to use as well:

import pickle

object = someClass()

file = open(filename, 'wb') # Create external file

pickle.dump(object, file) # Save object in file

import pickle

file = open(filename, 'rb')

object = pickle.load(file) # Fetch it back later

Pickling converts in-memory objects to serialized byte streams (really, strings), which may be stored in files, sent across a network, and so on; unpickling converts back from byte streams to identical in-memory objects. Shelves are similar, but they automatically pickle objects to an access-by-key database, which exports a dictionary-like interface:

import shelve

object = someClass()

dbase = shelve.open('filename')

dbase['key'] = object # Save under key

import shelve

dbase = shelve.open('filename')

object = dbase['key'] # Fetch it back later

In our pizza shop example, using classes to model employees means we can get a simple database of employees and shops with little extra work—pickling such instance objects to a file makes them persistent across Python program executions:

>>> from pizzashop import PizzaShop

>>> shop = PizzaShop()

>>> shop.server, shop.chef

(, )

>>> import pickle

>>> pickle.dump(shop, open('shopfile.dat', 'wb'))

This stores an entire composite shop object in a file all at once. To bring it back later in another session or program, a single step suffices as well. In fact, objects restored this way retain both state and behavior:

>>> import pickle

>>> obj = pickle.load(open('shopfile.dat', 'rb'))

>>> obj.server, obj.chef

(, )

>>> obj.order('Sue')

Sue orders from

Bob makes pizza

oven bakes

Sue pays for item to

See the standard library manual and later examples for more on pickles and shelves.

* * *

OOP and Delegation: “Wrapper” Objects

Beside inheritance and composition, object-oriented programmers often also talk about something called delegation, which usually implies controller objects that embed other objects to which they pass off operation requests. The controllers can take care of administrative activities, such as keeping track of accesses and so on. In Python, delegation is often implemented with the __getattr__ method hook; because it intercepts accesses to nonexistent attributes, a wrapper class (sometimes called a proxy class) can use __getattr__ to route arbitrary accesses to a wrapped object. The wrapper class retains the interface of the wrapped object and may add additional operations of its own.

Consider the file trace.py, for instance:

class wrapper:

def __init__(self, object):

self.wrapped = object # Save object

def __getattr__(self, attrname):

print('Trace:', attrname) # Trace fetch

return getattr(self.wrapped, attrname) # Delegate fetch

Recall from Chapter 29 that __getattr__ gets the attribute name as a string. This code makes use of the getattr built-in function to fetch an attribute from the wrapped object by name string—getattr(X,N) is like X.N, except that N is an expression that evaluates to a string at runtime,

Return Main Page Previous Page Next Page

®Online Book Reader