The first example would actually be equivalent to something like
while True:
bytes = io.get(x)
if not bytes:
break
...
which I think is objectively less readable.In the second example, you have an extra call to foo for every element of stuff. If foo(z) is expensive, you'd probably want to write this as
[bar(x) for x in map(foo, stuff) if x]
instead - which I personally don't mind, but it's arguably not as clear as having the in-line assignment expression.