def walk(self, start, end):
s = start.path<EOL>e = end.path<EOL>if start.root != end.root:<EOL><INDENT>msg = "<STR_LIT>" % (start, end)<EOL>raise WalkError(msg)<EOL><DEDENT>c = Walker.__calc_common(s, e)<EOL>assert c[<NUM_LIT:0>] is start.root<EOL>len_c = len(c)<EOL>if start is c[-<NUM_LIT:1>]:<EOL><INDENT>up = tuple()<EOL><DEDENT>else:<EOL><INDENT>up = tuple(reversed(s[len_c:]))<EOL><DEDENT>if end is c[-<NUM_LIT:1>]:<EOL><INDENT>down = tuple()<EOL><DEDENT>else:<EOL><INDENT>down = e[len_c:]<EOL><DEDENT>return up, c[-<NUM_LIT:1>], down<EOL>
Walk from `start` node to `end` node.

Returns:
    (upwards, common, downwards): `upwards` is a list of nodes to go upward to.
    `common` top node. `downwards` is a list of nodes to go downward to.

Raises:
    WalkError: on no common root node.

>>> from anytree import Node, RenderTree, AsciiStyle
>>> f = Node("f")
>>> b = Node("b", parent=f)
>>> a = Node("a", parent=b)
>>> d = Node("d", parent=b)
>>> c = Node("c", parent=d)
>>> e = Node("e", parent=d)
>>> g = Node("g", parent=f)
>>> i = Node("i", parent=g)
>>> h = Node("h", parent=i)
>>> print(RenderTree(f, style=AsciiStyle()))
Node('/f')
|-- Node('/f/b')
|   |-- Node('/f/b/a')
|   +-- Node('/f/b/d')
|       |-- Node('/f/b/d/c')
|       +-- Node('/f/b/d/e')
+-- Node('/f/g')
    +-- Node('/f/g/i')
        +-- Node('/f/g/i/h')

Create a walker:

>>> w = Walker()

This class is made for walking:

>>> w.walk(f, f)
((), Node('/f'), ())
>>> w.walk(f, b)
((), Node('/f'), (Node('/f/b'),))
>>> w.walk(b, f)
((Node('/f/b'),), Node('/f'), ())
>>> w.walk(h, e)
((Node('/f/g/i/h'), Node('/f/g/i'), Node('/f/g')), Node('/f'), (Node('/f/b'), Node('/f/b/d'), Node('/f/b/d/e')))
>>> w.walk(d, e)
((), Node('/f/b/d'), (Node('/f/b/d/e'),))

For a proper walking the nodes need to be part of the same tree:

>>> w.walk(Node("a"), Node("b"))
Traceback (most recent call last):
  ...
anytree.walker.WalkError: Node('/a') and Node('/b') are not part of the same tree.