Intermediate variable in a list comprehension for simultaneous filtering and transformation

Is this really the best way?

Well, it does work efficiently and if you really, really want to write oneliners then it's the best you can do.

On the other hand, a simple 4 line function would do the same much clearer:

def normfilter(vecs, min_norm):
    for x,y in vecs:
        n = (x**2.+y**2.)**-0.5
        if min_norm < n:
            yield (x*n,y*n)

normalized = list(normfilter(vectors, 0.4))

Btw, there is a bug in your code or description - you say you filter out short vectors but your code does the opposite :p


Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), it's possible to use a local variable within a list comprehension in order to avoid calling multiple times the same expression:

In our case, we can name the evaluation of (x**2.+y**2.)**-.5 as a variable n while using the result of the expression to filter the list if n is inferior than 0.4; and thus re-use n to produce the mapped value:

# vectors = [(1, 1), (1, 2), (2, 2), (3, 4)]
[(x*n, y*n) for x, y in vectors if (n := (x**2.+y**2.)**-.5) < .4]
# [(0.7071067811865476, 0.7071067811865476), (0.6000000000000001, 0.8)]