
On Fri, Apr 20, 2018 at 6:32 PM, Paul Moore <p.f.moore@gmail.com> wrote:
def read_document(file): doc = "" while (token := file.get_next_token()) != "END": doc += token return doc
The loop condition is "while the token is not END", or "while get_next_token() doesn't return END", depending on your point of view. Is it "more readable" to put that condition into the while header, or to use an infinite loop and a break statement, or to duplicate a line of code before the loop and at the bottom of the loop? Which one best expresses the programmer's intention?
The version that captures the value and tests it. I agree completely here. But we do have other options:
def read_document(file): doc = "" for token in token_stream(file, terminator="END"): doc += token return doc
(This point about rewriting to use for and an iterator applies to Chris Barker's fp.readline() example as well).
Sure, token_stream might need a loop-and-a-half internally[1]. But from the user's point of view that's "low level" code, so not so important (ultimately, this is all about abstracting intent). And people maybe aren't used to writing "helper" iterators quite this freely, but that's a matter of education. So agreed - assignment expressions help with loop-and-a-half constructs. But we have other ways of dealing with them, so that's a relatively manageable situation.
It's *still* all about cost-benefit trade-offs, with no clear winner (in my view).
You can always add another level of indirection. Always. Pushing something off into another function is helpful ONLY if you can usefully name that function, such that anyone who's reading the calling code can ignore the function and know everything they need to know about it. Otherwise, all you've done is force them to look elsewhere for the code. A bunch of single-use helper functions does not generally improve a module.
[1] Although actually not - in *this* case, iter(file.get_next_token, 'END') is exactly what you need. But I concede that it's possible to demonstrate examples where that isn't the case.
The easiest way is to pick any comparison other than equality. If you want "is" / "is not", or if there are several termination conditions (so the check is "in {x, y, z}"), iter() can't help you. ChrisA