Notice that calling Bob’s tax method works even though we didn’t import the Person
class in this last session. Python is smart enough to link this object back to its original
class when unpickled, such that all the original methods are available through fetched
objects.
Changing Classes of Objects Stored in Shelves
Technically, Python reimports a class to re-create its stored instances as they are fetched
and unpickled. Here’s how this works:
Store
When Python pickles a class instance to store it in a shelve, it saves the instance’s
attributes plus a reference to the instance’s class. In effect, pickled class instances
in the prior example record the self attributes assigned in the class. Really, Python
serializes and stores the instance’s dict attribute dictionary along with enough
source file information to be able to locate the class’s module later—the names of
the instance’s class as well as its class’s enclosing module.
Fetch
When Python unpickles a class instance fetched from a shelve, it re-creates the
instance object in memory by reimporting the class using the save class and module
name strings, assigning the saved attribute dictionary to a new empty instance, and
linking the instance back to the class. This is be default, and it can be tailored by
defining special methods that will be called by pickle to fetch and store instance
state (see the Python library manual for details).
The key point in this is that the class and stored instance data are separate. The class
itself is not stored with its instances, but is instead located in the Python source file and
reimported later when instances are fetched.
The downside of this model is that the class must be importable to load instances off
a shelve (more on this in a moment). The upside is that by modifying external classes
in module files, we can change the way stored objects’ data is interpreted and used
without actually having to change those stored objects. It’s as if the class is a program
that processes stored records.
To illustrate, suppose the Person class from the previous section was changed to the
source code in Example 17-3.
Example 17-3. PP4E\Dbase\person.py (version 2)
"""
a person object: fields + behavior
change: the tax method is now a computed attribute
"""
class Person:
def init(self, name, job, pay=0):
self.name = name
1320 | Chapter 17: Databases and Persistence