#! /usr/bin/python3 ## a common use of classes is to implement data structures ## this is an example of a stack, ## which is a LIFO - last in first out - structure ## it is a collection. ## items are added to the stack with push and removed with pop ## ----------------------------------------------------------- ## we will see that the python virtual machine for interpreting ## byte code is based on a stack architecture. ## ----------------------------------------------------------- class stack: ## there is a subtle bug here def __init__(self, items = []): # fix the bug self.items = items[:] self.size = len(items) def __repr__(self): return "stack({})".format(list(self.items)) def isEmpty(self): return self.items == [] def push(self, item): self.items.append(item) self.size += 1 def peek(self): if self.isEmpty(): print ("Error: stack is empty") else: return self.items[-1] def pop(self): if self.isEmpty(): print ("Error: stack is empty") else: self.size -= 1 return self.items.pop() ## swap the top two items in the stack def rotate(self): if self.size < 2: print ("Error: stack has fewer than 2 elements") else: self.items[-1], self.items[-2] = self.items[-2], self.items[-1] ## define the iterator for stack. Used in for or list comprehension def __iter__(self): """Return iterator for the stack.""" if self.isEmpty(): return None else: index = self.size -1 while index >= 0: yield self.items[index] index -= 1 ## check to see if two stacks are equal (==) def __eq__(self, other): if type(other) != type(self): return False if self.items == other.items: return True else: return False # copy constructor - clone the current instance def copy(self): s = stack(self.items) return s s = stack() s.push(1) s.push(2) s.push(3) s.push(4) ## test the iterator def test(s): for i in s: print (i) return [x for x in s] ## revstr uses a stack to reverse a string ## ---------------------------------------- def revstr(str): s = stack() for c in str: s.push(c) result = [] while (not s.isEmpty()): result.append(s.pop()) return ''.join(result)