7 ms·
Walrus operator IMO is a huge mistake. It saves fuck all time/space, but introduces an entire new operator that probably added more complexity, edge cases and q
by systemvoltage 4y ago
Walrus operator IMO is a huge mistake. It saves fuck all time/space, but introduces an entire new operator that probably added more complexity, edge cases and quirks than the benefits it provides. Terrible idea.
Worse, no one uses it. I've yet to come across anyone that advocates it or remembers it.
- asicsp 4y agoI use it for simple cases: >>> if m := re.search(r'(.*)s', 'oh!'): ... print(m[1]) ... >>> if m := re.search(r'(.*)s', 'awesome'): ... print(m[1]) ... awe
- systemvoltage 4y agoThe question one has to ask is whether it is worth the additional complexity and a dedicated operator. I am sure it is ever so slightly useful, but I am not convinced it is worth the trouble. Feature creep is programming language's worse enemy after a certain maturity level. I absolutely love Go in this matter. They took forever to add Generics and generally sides with stability over features.
- plumeria 4y agoThe let expression syntax in OCaml is a nice alternative: let some_func () = 5 let a = some_func () in if a < 5 then "<5" else ">=5"
- jreese 4y agoI actually just used it to what I would say was a perfect example of where it legitimately improved code readability while maintaining pythonic constructs: values = [ value for line in buffer.readlines() if (value := line.strip()) ] Previously, I would have needed to either duplicate effort like: values = [ line.strip() for line in buffer.readlines() if line.strip() ] Or used a sub-generator: values = [ value for value in ( line.strip() for line buffer.readlines() ) if value ] Or rewritten it altogether using a (slower) for loop calling append each time: values = [] for line in buffer.readlines(): line = line.strip() if line: values.append(line) The assignment expression is perfect for this sort of use case, and is a clear win over the alternatives IMO. Edit: fixed initial example
- zamadatix 4y agoTo me the second version seems not only clearer/more direct to follow but also is a few characters shorter anyways.
- japanuspus 4y agoBut the second version needs to run `.strip` twice. It might not make much of a difference for `strip` -- but it still hurts my eyes, and could be an actual performance issue for other operations.
- pydry 4y agoRunning strip twice makes it more explicit and readable IMHO - it's then abundantly clear that it's being run as a check and as a way of populating the list.
- compressedgas 4y agoYou can write it this way: values = [ value for line in buffer.readlines() for value in (line.strip(),) if value ]
- jreese 4y agoFWIW, that version ends up being slower, because you're constructing and iterating over a tuple for every iteration, which incurs a similar cost to running `.strip()` twice. The sub-generator example I gave is better because you're only constructing the generator expression once, and requires less overhead for each iteration.
- d0mine 4y agoIt is unlikely (unless there is a benchmark that says otherwise). Before the walrus operator, the single item loop could have been used: nonblank = [value for line in file for value in [line.strip()] if value]
- 4y ago
- dragonwriter 4y agoWalrus avoids stuttering in constructs like comprehensions/genexps which greatly improves readability. (And avoids using less basically readable constructs, like explicit imperative loops, to avoid the visual noise of stuttering.)
- quietbritishjim 4y agoI'm surprised no one's mentioned a while loop yet: start = 0 while (end := my_str.find("x", start)) != -1: print(my_str[start:end]) start = end + 1 vs start = 0 while True: end = my_str.find("x", start) if end == -1: break print(my_str[start:end]) start = end + 1 I'm still on the fence myself so I sympathise with your view, but the first version is certainly a bit tidier in this case.
- paulluuk 4y agoI never use the walrus operator but your second example is pretty typical and it does indeed look a lot cleaner with the walrus operator.
- Woden501 4y agoSure it's "tidier" if by that you mean smaller. Someone who doesn't work in Python all the time and isn't aware of these kinds of operators is going to have to spend a decent amount of time unpacking what the hell that all means whereas someone can take one look at the standard while loop, see the logic laid out plainly, understand what's happening, and make changes, if necessary, fairly easily. Unless there's a performance benefit to an operator like this I'll forgo "tidy" for clear any day of the week. Then again I'm just a senior dev whose only professional experience with Python was maintaining other people's Python projects who never had to touch them again after they wrote them, and who used Python for things Python should not have been used for just because it's "easy" to write.
- frogcoder 4y agoFunny, I think the walrus operator makes code cleaner and easier to understand. Many of my code were like this: foo = one_or_none() if foo: do_stuff(foo) Now I have the following: if foo := one_or_none(): do_stuff(foo) This kind of code happens quite frequently, looks nicer with walrus operator to me.
- digisign 4y agoWould have been more Pythonic as: if one_or_none() as foo: do_stuff(foo)
- aix1 4y agoI didn't recognize this use of "as" as valid Python, but tried it in 3.9 just to be sure. Got a syntax error (as expected). I am not fully up to speed with 3.10, but quickly checked the docs and it doesn't appear to have been added in 3.10 either. Let me know if I'm missing something.
- dragonwriter 4y agoHonestly, for this specific case, I prefer one_or_none() to return an iterable with zero or one items, and then just doing: for foo in one_or_none(): do_stuff(foo) If you don't control one_or_none, but it returns an Optional, you can wrap it with something like: def optional_to_tuple(opt_val: Optional[T]) -> Tuple[]|Tuple[T]: return (opt_val,) if opt_val is not None else ()