return len(self.stack) # len(instance), not instance
def add(self, other):
return Stack(self.stack + other.stack) # instance1 + instance2
def mul(self, reps):
return Stack(self.stack reps) # instance reps
def getitem(self, offset): # see also iter
return self.stack[offset] # instance[i], [i:j], in, for
def getattr(self, name):
return getattr(self.stack, name) # instance.sort()/reverse()/..
Now distinct instances are created by calling the Stack class like a function. In most
respects, the Stack class implements operations exactly like the stack module in Ex-
ample 18-1. But here, access to the stack is qualified by self, the subject instance object.
Each instance has its own stack attribute, which refers to the instance’s own list. Fur-
thermore, instance stacks are created and initialized in the init constructor
method, not when the module is first imported. Let’s make a couple of stacks to see
how all this works in practice:
>>> from stack2 import Stack
>>> x = Stack() # make a stack object, push items
>>> x.push('spam')
>>> x.push(123)
>>> x # __repr__ prints a stack
[Stack:[123, 'spam']]
>>> y = Stack() # two distinct stack objects
>>> y.push(3.1415) # they do not share content
>>> y.push(x.pop())
>>> x, y
([Stack:['spam']], [Stack:[123, 3.1415]])
>>> z = Stack() # third distinct stack object
>>> for c in 'spam': z.push(c)
...
>>> while z: # __len__ tests stack truth
... print(z.pop(), end=' ')
...
m a p s >>>
>>> z = x + y # __add__ handles stack +
>>> z # holds three different types
[Stack:['spam', 123, 3.1415]]
>>> for item in z: # __getitem__ does for
... print(item, end=' ')
...
spam 123 3.1415 >>>
>>> z.reverse() # __getattr__ delegates to list
>>> z
[Stack:[3.1415, 123, 'spam']]
Implementing Stacks| 1365