For instance, to add logic that monitors the number of stack operations a program
performs, we’d have to add code around each hardcoded stack operation. In a large
system, this update may be nontrivial work. As we’ll discuss in Chapter 20, we may
also decide to move stacks to a C-based implementation, if they prove to be a perform-
ance bottleneck. As a general rule, hardcoded operations on built-in data structures
don’t support future migrations as well as we’d sometimes like.
As we’ll see later, built-in types such as lists are actually class-like objects in Python
that we can subclass to customize, too. This might be only a partial fix, though; unless
we anticipate future changes and make instances of a subclass, we may still have a
maintenance issue if we use built-in list operations directly and ever want to extend
what they do in the future.
A Stack Module
Of course, the real solution to such code maintenance dilemmas is to encapsulate—
that is, wrap up—stack implementations behind interfaces, using Python’s code reuse
tools. As long as clients stick to using the interfaces, we’re free to change the interfaces’
implementations arbitrarily without having to change every place they are called. Let’s
begin by implementing a stack as a module containing a Python list, plus functions to
operate on it; Example 18-1 shows one way to code this.
Example 18-1. PP4E\Dstruct\Basic\stack1.py
"a shared stack module"
stack = [] # on first import
class error(Exception): pass # local excs, stack1.error
def push(obj):
global stack # use 'global' to change
stack = [obj] + stack # add item to the front
def pop():
global stack
if not stack:
raise error('stack underflow') # raise local error
top, *stack = stack # remove item at front
return top
def top():
if not stack: # raise local error
raise error('stack underflow') # or let IndexError occur
return stack[0]
def empty(): return not stack # is the stack []?
def member(obj): return obj in stack # item in stack?
def item(offset): return stack[offset] # index the stack
def length(): return len(stack) # number entries
def dump(): print('<Stack:%s>' % stack)
1362 | Chapter 18: Data Structures