5 ms·
I actually just used it to what I would say was a perfect example of where it legitimately improved code readability while maintaining pythonic constructs:
by jreese 4y ago
I 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]
- weird-eye-issue 4y agovalues = list(filter(None, [line.strip() for line in buffer.readlines()]))
- pmontra 4y agoOr, in a different language open("file", "r").readlines. map{|line| line.strip}. filter{|line| line != ""} or some smarter but less readable ways. I prefer the left-to-right transformations style to Python's list comprehension and inside-to-outside function composition. The reason is that it reminds me of how data flow into *nix pipelines. I spent decades working with them and I've been working with Ruby for the last half of that time. With Python in the last quarter of my career. It's a matter of choices and preferences of the original designed of the language. Both ways work.
- quietbritishjim 4y agoNot sure if this was your intention or not, but to me that proves the usefulness of the walrus operator: the first snippet in the parent comment seems far clearer to me, even though I'm fairly familiar with the functional operators.
- weird-eye-issue 4y agoIt's a very useful pattern once you know what it does, sort of like the walrus operator
- quietbritishjim 4y agoI was careful to pre-empt this exact response in my original comment: I do know what it does. The fact remains that it's less readable (IMO) because of the density of line noise and the lack of common structural elements (like if and for - I suppose filter and map fulfill this but their parameter separate out elements that ought to be next to each other). I do think that my preference, however slight, would remain no matter how much time I spent with the functional versions.
- eidorb 4y agoI may have gone with the following. Yes, some characters are repeated, but I'm not playing code golf. stripped_lines = (line.strip() for line in buffer.readlines()) non_empty_stripped_lines = [line for line in stripped_lines if stripped_lines]
- systemvoltage 4y agoWay better IMO. Clear variable names. No golfing. Breaking down things in clear steps is underrated I think.