CoconutBandit - 10 months ago 41

Python Question

I have a directed graph structure consisting of nodes and edges both of which subclass an Event parent class. Depending on external events, edges can either be active or inactive. I then find all the directed paths from a given node to the root node, but I really only care about the nodes along the way, not the edges. For instance, to convert from a set of edges to a set of nodes I use:

`>>> paths`

[[<Edge F>, <Edge B>]]

>>> lst = [set(map(lambda e: e.tail, path)) for path in paths]

where path is a list of edges. This is what confuses me: when I go to check the contents of

`lst`

`>>> lst`

[set([<Node 2>, <Node 1>])]

>>> [type(n) for n in path for path in lst]

[<class 'libs.network.Edge'>, <class 'libs.network.Edge'>]

>>> [type(n) for n in lst[0]]

[<class 'libs.network.Node'>, <class 'libs.network.Node'>]

Why aren't these two ways of accessing the type information the same?

Answer

You have your list comprehension order wrong. Nested loops are listed from *left to right*.

So the expression

```
[type(n) for n in path for path in lst]
```

is executed as

```
for n in path:
for path in lst:
type(n)
```

so `n`

is taken from some random pre-assigned `path`

variable you had before, and it is *that variable* that contains `Edge`

instances. Those objects have *nothing* to do with the contents of `lst[0]`

you loop over in your other expression.

You probably wanted to do this the other way around:

```
[type(n) for path in lst for n in path]
```

so that `path`

is actually set from `lst`

*before* you iterate over it.

Source (Stackoverflow)