8.7 The UserList, UserDict, and UserString Modules
The
UserList, UserDict, and
UserString modules each supply one class, with the
same name as the respective module, that implements all the methods
needed for the class's instances to be mutable
sequences, mappings, and strings, respectively. When you need such
polymorphism, you can subclass one of these classes and override some
methods rather than have to implement everything yourself. In Python
2.2 and later, you can subclass built-in types
list, dict, and
str directly, to similar effect (see Section 5.2). However, these modules can still be handy if
you need to create a classic class in order to keep your code
compatible with Python 2.1 or earlier.
Each
instance of one of these classes has an attribute called
data that is a Python object of the corresponding
built-in type (list, dict, and
str, respectively). You can instantiate each class
with an argument of the appropriate type (the argument is copied, so
you can later modify it without side effects).
UserList and UserDict can also
be instantiated without arguments to create initially empty
containers.
Module UserString also supplies class
MutableString, which is very similar to class
UserString except that instances of
MutableString are mutable. Instances of
MutableString and its subclasses cannot be keys
into a dictionary. Instances of both UserString
and MutableString can be Unicode strings rather
than plain strings: just use a Unicode string as the initializer
argument at instantiation time.
If you subclass UserList,
UserDict, UserString, or
MutableString and then override _ _init_
_, make sure the _ _init_ _ method you
write can also be called with one argument of the appropriate type
(as well as without arguments for UserList and
UserDict). Also be sure that your _
_init_ _ method explicitly and appropriately calls the
_ _init_ _ method of the superclass, as usual.
For maximum efficiency, you can arrange for your subclass to inherit
from the appropriate built-in type when feasible (i.e., when your
program runs with Python 2.2), but keep the ability to fall back to
these modules when necessary (i.e., when your program runs with
Python 2.1). Here is a typical idiom you can use for this purpose:
try: # can we subclass list?
class _Temp(list):
pass
except: # no: use UserList.UserList as base class
from UserList import UserList as BaseList
else: # yes: remove _Temp and use list as base class
del _Temp
BaseList = list
class AutomaticallyExpandingList(BaseList):
"""a list such that you can always set L[i]=x even for a large i:
L automatically grows, if needed, to make i a valid index."""
def _ _setitem_ _(self, idx, val):
self.extend((1+idx-len(self))*[None])
BaseList._ _setitem_ _(self, idx, val)
|