Q:

walrus operator: if contition with strange results

i was playing around (in relation with this question) with the walrus operator := which will be available in python 3.8.
with
def f(x):
    return x**3

old_list =  = list(range(9))

this works as expected (never mind that the example is pointless...):
new_list = [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
# [1, 8, 343]

this is valid and runs, but returns something unexpected:
new_list = [fx := f(x) for x in old_list if fx in {1, 8, 343}]
# []

what is happening here?

A:

TL;DR your 2nd one is not "that" valid:
>>> old_list = list(range(9))
>>> f = lambda x: x ** 3
>>> [fx := f(x) for x in old_list if fx in {1, 8, 343}]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
NameError: name 'fx' is not defined
>>> 

Explanation
In your first list comprehension, [fx for x in old_list if (fx := f(x))  in {1, 8, 343}], the fx := creates a variable outside of it:
>>> old_list = list(range(9))
>>> f = lambda x: x ** 3
>>> [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
[1, 8, 343]
>>> fx
512

If you run [fx := f(x) for x in old_list if fx in {1, 8, 343}] afterwards, it will go like this:

for x in old_list binds x to 0
if fx in {1, 8, 343}, fx being the old 512 which is false
as the if is false, the "select" (left) part is not executed, no call to f, no rebinding of fx, fx is still 512.
assign x as the 2nd element of old_list, being 1
...

We can double check this interpretation like this:
>>> [print("no no no") for x in old_list if fx in {1, 8, 343}]
[]

no no no is never printed, so this side is never executed (as fx is 512, not in the set).

