6 ms·
The issue, in my opinion, is when you want something like this: while m := f(many, args): # do stuff with m Now, if you're writing this in Python
by 3PS 7y ago
The issue, in my opinion, is when you want something like this:
while m := f(many, args):
# do stuff with m
Now, if you're writing this in Python 3.7, you often end up with some code duplication:
m = f(many, args)
while m:
# do stuff with m
m = f(many, args) # duplicate
Or something like this:
while True:
m = f(many, args)
if not m:
break
# do stuff with m
Personally, I consider the last version to be the most elegant, but still something of an anti-pattern. So I welcome this new operator.
- hermitdev 7y agoI literally wrote your last example twice last week to hash files in 4k chunks. Those 4 lines would be reduced to 1 with the walrus operator. I welcome it, as well. Edit: 1 line, not 2 (excluding the "do stuff")
- cellularmitosis 7y agoThis comes up in recursive descent implementations as well https://gist.github.com/cellularmitosis/53913ad229bad5d0a3bb92f196fdda7b https://gist.github.com/cellularmitosis/53913ad229bad5d0a3bb...
- ygrechuk 7y agoWhy not something like this: def f_iter(many, args): while True: m = f(many, args) if m: yield m else: raise StopIteration ... for m in f_iter(many, args): # do stuff with m This way you’re isolating all the initialization logic, error handling, etc. And you can focus on your domain logic in your client code.
- repsilat 7y agoAnd less reasonably, something similar for regular expressions: for m in filter([re.match(...)], bool): ... ;-)
- mlevental 7y agoso i should write a whole other function that iterates over a list instead of being happy that := exists?
- throwaway744678 7y agoYes! No pain, no gain!
- ciupicri 7y agoInstead of raising StopIteration you could also just return from the function. You could also make it a bit shorter if you swap the if branches. def f_iter(many, args): while True: m = f(many, args) if not m: return yield m
- zb 7y agoInstead of raising StopIteration you have to return from the function, otherwise you'll just get a RuntimeError starting with Python 3.7.
- ciupicri 7y agoYou're right. The [changelog] for Python 3.7 states: > [bpo-32670]: Enforce [PEP 479] for all code. This means that manually raising a StopIteration exception from a generator is prohibited for all code, regardless of whether ‘from __future__ import generator_stop’ was used or not. [changelog]: https://docs.python.org/3.7/whatsnew/changelog.html#id115 https://docs.python.org/3.7/whatsnew/changelog.html#id115 [bpo-32670]: https://bugs.python.org/issue32670 https://bugs.python.org/issue32670 [PEP 479]: https://www.python.org/dev/peps/pep-0479/ https://www.python.org/dev/peps/pep-0479/
- bvrmn 7y agoPython has built-in facilities for that, there is no need to write wrapper by yourself. from functools import partial with open('mydata.db', 'rb') as f: for block in iter(partial(f.read, 64), b''): process_block(block)
- xapata 7y agoThat last one isn't an anti-pattern. That's the pattern concluded best for do-while in the discussion of PEP-315. https://www.python.org/dev/peps/pep-0315/#notice https://www.python.org/dev/peps/pep-0315/#notice
- pyrale 7y agoThe last version clearly exposes that you have an infinite loop. This is something hidden by the `while(evaluate)` expression. Also if it comes to pure form I would have preferred `while (evaluate) as x:` out of establishing a parallel with existing syntax, but that's not very important.
- pdpi 7y agoOn the contrary: the loop isn’t fundamentally infinite, it’s just an artefact of the language that you have to write it that way. The walrus lets you put the termination where it belongs.
- pyrale 7y agoI don't understand that the walrus has any significance with regards to the `while` loop termination. it's the nature of the evaluated expression that makes a difference, more precisely, whether it will return something that is cast to False. In that sense, while loops over expressions always require knowledge of the expression to understand the semantic. On the other hand, something like: while True: with x as y: print(y) would not require understanding of x to understand the intent. Therefore it is not semantically equivalent to: while x as y: print(y) Note that in both cases, `:=` is strictly equivalent to `as` as it is defined for `with`. That is a matter of personal preference.