Path finder for network link wiring I have created a Path finder.
The aim is to find ALL paths that join a Point A to a Point B.
I have defined an object Segment which is a link between two assets.
It is readable in both directions.
==&gt; Segment(A-&gt;B) === Segment(B&lt;-A)

Here is my code:
# Exemple Path finder

class Segment:
  # A segment is a link (physical, radio, logical) beetween two assets
  def __init__(self, sku, e1, e2, re1, re2):
    # The SKU is the unique ID of the segment
    # A segment as two endpoint that can be inversable
    self.sku = sku
    self.sku_endpoint_1 = e1
    self.sku_endpoint_2 = e2
    self.reverse_sku_endpoint_1 = re1
    self.reverse_sku_endpoint_2 = re2

# We can instanciante a segment like that

seg1 = Segment(&quot;SEGMENT1&quot;,&quot;A&quot;, &quot;B&quot;, &quot;B&quot;, &quot;A&quot;)
seg2 = Segment(&quot;SEGMENT2&quot;,&quot;B&quot;, &quot;C&quot;, &quot;C&quot;, &quot;B&quot;)
seg3 = Segment(&quot;SEGMENT3&quot;,&quot;C&quot;, &quot;D&quot;, &quot;D&quot;, &quot;C&quot;)
seg4 = Segment(&quot;SEGMENT4&quot;,&quot;C&quot;, &quot;E&quot;, &quot;E&quot;, &quot;C&quot;)
seg5 = Segment(&quot;SEGMENT5&quot;,&quot;E&quot;, &quot;A&quot;, &quot;A&quot;, &quot;E&quot;)
seg6 = Segment(&quot;SEGMENT6&quot;,&quot;E&quot;, &quot;D&quot;, &quot;D&quot;, &quot;E&quot;)

# Then create a liste of segment
liste_segments = [seg1, seg2, seg3, seg4, seg5, seg6]

--
# The function below allow to find neibhors of a segment
def neighbors(liste_segments, node):
  for segment in liste_segments:
    if node == segment.sku_endpoint_1:
      yield segment

--
# And the function below solve all paths existing beetween an start et end.
def solve(liste_segments, s, e, current_path=None, nb_call=0):
  nb_call += 1
  if nb_call == 1:
    # We create a new liste with the inversable values to have all possibility of linking
    liste_segments = clone(liste_segments)
  if current_path is None:
    current_path = []
  if s == e:
    # Here, we end the function because we found the end.
    yield current_path
  else:
    # Else we call recursively the solve function on each neibhors
    for node in neighbors(liste_segments, s):
      print(node.sku_endpoint_1, node.sku_endpoint_2)
      if node not in current_path:
        for result in solve(liste_segments, node.sku_endpoint_2 , e, current_path + [node], nb_call):
          yield result

--
# The yield function return a generator
# The function here create a dictionnary of all paths found.
# On all paths we check if the paths is meaningful.
# Ex: if a segment is found twice on the same path...this is not meaningful.
# So we delete the entry from the dict to keep only understanding paths.
def list_to_dict(paths):
  d = {}
  index = 0
  for path in paths:
    index+=1
    d[index] = []
    for segment in path:
      d[index].append(segment.sku)
  
  to_del = []
  for k, v in d.items():
    temp = []
    for seg in v:
      if seg not in temp:
        temp.append(seg)
      else:
        if k not in to_del:
          to_del.append(k)
  for i in to_del:
    del d[i]
  return d

--
# The clone function create a new list of segment with all possibility.

def clone(liste_segments):
  new_list_segments = []
  for seg in liste_segments:
    new_list_segments.append(Segment(seg.sku, seg.sku_endpoint_1, seg.sku_endpoint_2, &quot;&quot;, &quot;&quot;))
    new_list_segments.append(Segment(seg.sku, seg.reverse_sku_endpoint_1, seg.reverse_sku_endpoint_2, &quot;&quot;, &quot;&quot;))
  return new_list_segments

Is my code pythonic? What could be changed?
If you want to work with graphs in Python, you should have a look at the excellent module networkx. It has (usually fast) implementations of the most common (and many not so common) operations on directed and undirected graphs.
Your case in particular, finding all simple paths (i.e. paths without repeating nodes) between two nodes, is already implemented:
import networkx as nx

g = nx.Graph()  # bi-directional edges. Use nx.DiGraph() if you want to explicitly specify directions
g.add_edges_from([(&quot;A&quot;, &quot;B&quot;), (&quot;B&quot;, &quot;C&quot;), (&quot;C&quot;, &quot;D&quot;), (&quot;C&quot;, &quot;E&quot;), (&quot;E&quot;, &quot;A&quot;)])
g.add_edge(&quot;E&quot;, &quot;D&quot;)  # can also add individual edges

for path in nx.all_simple_paths(g, source=&quot;A&quot;, target=&quot;B&quot;):
    print(path)

# ['A', 'B']
# ['A', 'E', 'C', 'B']
# ['A', 'E', 'D', 'C', 'B']

If you want to associate data with each edge and get back only this data, this is also possible:
g = nx.Graph()  # bi-directional edges. Use nx.DiGraph() if you want to explicitly specify directions
g.add_edges_from([(&quot;A&quot;, &quot;B&quot;, {&quot;sku&quot;: &quot;SEGMENT1&quot;}),
                  (&quot;B&quot;, &quot;C&quot;, {&quot;sku&quot;: &quot;SEGMENT2&quot;}),
                  (&quot;C&quot;, &quot;D&quot;, {&quot;sku&quot;: &quot;SEGMENT3&quot;}),
                  (&quot;C&quot;, &quot;E&quot;, {&quot;sku&quot;: &quot;SEGMENT4&quot;}),
                  (&quot;E&quot;, &quot;A&quot;, {&quot;sku&quot;: &quot;SEGMENT5&quot;})])
g.add_edge(&quot;E&quot;, &quot;D&quot;, sku=&quot;SEGMENT6&quot;)  # can also add individual edges

paths = nx.all_simple_paths(g, source=&quot;A&quot;, target=&quot;B&quot;)
for path in map(nx.utils.pairwise, paths):
    for edge in path:
        print(edge, g.edges[edge][&quot;sku&quot;])
    print()

# ('A', 'B') SEGMENT1
# 
# ('A', 'E') SEGMENT5
# ('E', 'C') SEGMENT4
# ('C', 'B') SEGMENT2
# 
# ('A', 'E') SEGMENT5
# ('E', 'D') SEGMENT6
# ('D', 'C') SEGMENT3
# ('C', 'B') SEGMENT2

It even allows you to easily visualize the graph:
import matplotlib.pyplot as plt

nx.draw(g, with_labels=True, node_color=&quot;white&quot;)
plt.show()


Or, more fancy:
pos = nx.spring_layout(g)
labels = dict(zip(g.edges, [g.edges[e][&quot;sku&quot;] for e in g.edges]))
nx.draw(g, with_labels=True, node_color=&quot;white&quot;, pos=pos)
nx.draw_networkx_edge_labels(g, pos=pos, edge_labels=labels)
plt.show()