How to reuse an expression in a comprehension expression?

Yes! Python 3.8 introduces the "Assignment operator" :=, which allows you to define a variable within the local scope of a single expression (e.g. a comprehension). In your example, you would do this:

result = {(p := next(k for k in ('path', 'subdir') if k in e)): some_func(p) 
          for e in bad_structure}

Disclaimer: this will not work in any version of python before 3.8.


You can use an intermediate comprehension to bind to a name:

result = {
    p: some_func(p)
    # bind intermediate result to p
    for p in (  # nested comprehension to produce intermediate result
        next(k for k in ('path', 'subdir') if k in e)
        for e in bad_structure
    )
 }

Instead of mapping directly to two separate expressions, it first maps to a common expression which then is mapped to two separate expressions.

You can pass along and rename an arbitrary number of values. Create a tuple in the inner comprehension, and unpack it to multiple names in the outer comprehension.

result = {
    p: some_func(e, p)
    for e, p in (
        (e, next(iter(e)))
        for e in bad_structure
    )
 }