It appears to me that it is not that straight forward to interchange classic while loops with assignment-expressions-loops keeping the code looking great.
Consider example1
:
>>> a = 0
>>> while (a := a+1) < 10:
... print(a)
...
1
2
3
4
5
6
7
8
9
and example2
:
>>> a = 0
>>> while a < 10:
... print(a)
... a += 1
...
0
1
2
3
4
5
6
7
8
9
How would you modify example1
in order to have the same output (not skipping the 0
) of example2
? (without changing a = 0
, of course)
Simple loops like your example should not be using assignment expressions. The PEP has a Style guide recommendations section that you should heed:
Simple loops should be implemented using iterables and
for
, they are much more clearly intended to loop until the iterator is done. For your example, the iterable of choice would berange()
:which is far cleaner and concise and readable than, say
The above requires extra scrutiny to figure out that in the loop
a
will start at0
, not at-1
.The bottom line is that you should not be tempted to 'find ways to use assignment statements'. Use an assignment statement only if it makes code simpler, not more complex. There is no good way to make your
while
loop simpler than afor
loop here.Your attempts at rewriting a simple loop are also echoed in the Tim Peters's findings appendix, which quotes Tim Peters on the subject of style and assignment expressions. Tim Peters is the author of the Zen of Python (among many other great contributions to Python and software engineering as a whole), so his words should carry some extra weight:
Bold emphasis mine.
A much better use-case for assignment expressions is the assigment-then-test pattern, especially when multiple tests need to take place that try out successive objects. Tim's essay quotes an example given by Kirill Balunov, from the standard library, which actually benefits from the new syntax. The
copy.copy()
function has to find a suitable hook method to create a copy of a custom object:The indentation here is the result of nested
if
statements because Python doesn't give us a nicer syntax to test different options until one is found, and at the same time assigns the selected option to a variable (you can't cleanly use a loop here as not all tests are for attribute names).But an assignment expression lets you use a flat
if / elif / else
structure:Those 8 lines are a lot cleaner and easier to follow (in my mind) than the current 13.
Another often-cited good use-case is the if there is a matching object after filtering, do something with that object, which currently requires a
next()
function with a generator expression, a default fallback value, and anif
test:which you can clean up a lot with the
any()
function