I made a post providing 3 iterative solutions: 2 using stack and 1 using Morris Traversal, with the complexity of Morris Traversal approach roughly explained. Hope it helps.

def preorderTraversal(self, root):
stack=[]
res=[]
while stack or root:
if root:
stack.append(root)
res.append(root.val)
root=root.left
else:
root=stack.pop()
root=root.right
return res

When using Morris, you'd better revert the TreeNode to original one, which means you should set the leftChild's rightmost TreeNode's right back to null.