I have an implementation of a function that sorts a stack. The function sortStack correctly sorts the stack but when I print the stack it seems to be modifying the initial parameter newStack2. Why does the return statement return None? Does it have something to do with pass by reference/aliasing?
class Stack():
def __init__(self):
self.stack = []
def push(self,val):
if len(self.stack)>=0:
self.stack.append(val)
else:
return None
def popOut(self):
if len(self.stack) > 0:
item = self.stack[-1]
self.stack.pop()
return item
else:
return None
def peek(self):
if self.isEmpty() == True:
return None
else:
return self.stack[-1]
def isEmpty(self):
if len(self.stack) == 0:
return True
else:
return False
def sortStack(stack1,stack2):
if stack1.isEmpty() is False:
if stack2.isEmpty() is True:
item = stack1.popOut()
stack2.push(item)
sortStack(stack1,stack2)
elif stack1.peek() < stack2.peek():
item = stack1.popOut()
stack2.push(item)
sortStack(stack1,stack2)
else:
item = stack1.popOut()
stack1.push(stack2.popOut())
stack2.push(item)
sortStack(stack1,stack2)
else:
stack1 = stack2
return stack1
if __name__ == '__main__':
newStack = Stack()
newStack.push(5)
newStack.push(4)
newStack.push(6)
newStack2 = Stack()
print(sortStack(newStack,newStack2))
print(newStack2.stack)
OUTPUT:
None
[6, 5, 4]
Insert a little basic tracing instrumentation:
indent = "" def sortStack(stack1,stack2): global indent print(indent + "ENTER sortStack", stack1.stack, stack2.stack) indent += " "
if stack1.isEmpty() is False:
if stack2.isEmpty() is True:
item = stack1.popOut()
stack2.push(item)
sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case A")
indent = indent[2:]
elif stack1.peek() < stack2.peek():
item = stack1.popOut()
stack2.push(item)
sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case B")
indent = indent[2:]
else:
item = stack1.popOut()
stack1.push(stack2.popOut())
stack2.push(item)
sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case C")
indent = indent[2:]
else:
print(indent + " sortStack at bottom", stack2.stack)
stack1 = stack2
print(indent + "LEAVE sortStack at bottom", stack1.stack)
indent = indent[2:]
return stack1
Output:
ENTER sortStack [5, 4, 6] []
ENTER sortStack [5, 4] [6]
ENTER sortStack [5] [6, 4]
ENTER sortStack [4] [6, 5]
ENTER sortStack [] [6, 5, 4]
sortStack at bottom [6, 5, 4]
LEAVE sortStack at bottom [6, 5, 4]
LEAVE sortStack case B
LEAVE sortStack case C
LEAVE sortStack case B
LEAVE sortStack case A
returned None
[6, 5, 4]
There's your problem: only your innermost call returns any value; the rest of them throw away what that innermost call passes back up the line. This returns None
.
REPAIR
Put the intended return value into a new variable; return that on any exit.
indent = "" def sortStack(stack1,stack2): global indent print(indent + "ENTER sortStack", stack1.stack, stack2.stack) indent += " "
if stack1.isEmpty() is False:
if stack2.isEmpty() is True:
item = stack1.popOut()
stack2.push(item)
result = sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case A")
indent = indent[2:]
elif stack1.peek() < stack2.peek():
item = stack1.popOut()
stack2.push(item)
result = sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case B")
indent = indent[2:]
else:
item = stack1.popOut()
stack1.push(stack2.popOut())
stack2.push(item)
result = sortStack(stack1,stack2)
print(indent + "LEAVE sortStack case C")
indent = indent[2:]
else:
result = stack2
print(indent + "LEAVE sortStack at bottom", result.stack)
indent = indent[2:]
return result
OUTPUT:
ENTER sortStack [5, 4, 6] []
ENTER sortStack [5, 4] [6]
ENTER sortStack [5] [6, 4]
ENTER sortStack [4] [6, 5]
ENTER sortStack [] [6, 5, 4]
LEAVE sortStack at bottom [6, 5, 4]
LEAVE sortStack case B
LEAVE sortStack case C
LEAVE sortStack case B
LEAVE sortStack case A
returned [6, 5, 4]
[6, 5, 4]