some more efficient than others so farour stacks have used slicing and extended sequence assignment to implement pushing and popping this method is relatively inefficientboth operations make copies of the wrapped list object for large stacksthis practice can add significant time penalty one way to speed up such code is to change the underlying data structure completely for examplewe can store the stacked objects in binary tree of tupleseach item may be recorded as pair(objecttree)where object is the stacked item and tree is either another tuple pair giving the rest of the stack or none to designate an empty stack stack of items [ , , , would be internally stored as tuple tree ( ,( ,( ( ,none)))this tuple-based representation is similar to the notion of "cons-cellsin lisp-family languagesthe object on the left is the carand the rest of the tree on the right is the cdr because we add or remove only top tuple to push and pop itemsthis structure avoids copying the entire stack for large stacksthe benefit might be significant the next classshown in example - implements these ideas example - pp \dstruct\basic\stack py "optimize with tuple pair treesclass stackdef __init__(selfstart=[])self stack none for in range(-len(start) )self push(start[- ]init from any sequence even other (fast)stacks push in reverse order def push(selfnode)self stack nodeself stack grow tree 'up/leftnew root tuple(nodetreedef pop(self)nodeself stack self stack return node remove root tuple typeerror if empty def empty(self)return not self stack is it 'none'def __len__(self)lentree self stack while treelentree len+ tree[ return len onlennot def __getitem__(selfindex)lentree self stack while len index and treelentree len+ tree[ if treereturn tree[ elseonx[ ]infor data structures visit right subtrees visit/count nodes indexerror if out-of-bounds