4 ms·
There's a lot of talk in this thread about Python going down-hill and becoming less obvious/simple. I rather like modern python, but I agree that some features
by stefco_ 7y ago
There's a lot of talk in this thread about Python going down-hill and becoming less obvious/simple. I rather like modern python, but I agree that some features (like async/await, whose implementation fractures functions and libraries into two colors [0]) seem like downgrades in "Pythonicity".
That said, I think some things have unquestionably gotten more "Pythonic" with time, and the := operator is one of those. In contrast, this early Python feature (mentioned in an article [1] linked in the main one) strikes me as almost comically unfriendly to new programmers:
> Python vowed to solve [the problem of accidentally assigning instead of comparing variables] in a different way. The original Python had a single "=" for both assignment and equality testing, as Tim Peters recently reminded him, but it used a different syntactic distinction to ensure that the C problem could not occur.
If you're just learning to program and know nothing about the distinction between an expression and a statement, this is about as confusing as shell expansion (another context-dependent syntax). It's way too clever to be Pythonic. The new syntax, though it adds an extra symbol to learn, is at least 100% explicit.
I'll add that := fixes something I truly hate: the lack of `do until` in Python, which strikes me as deeply un-Pythonic. Am I supposed to break out of `while True`? Am I supposed to set the variable before and at the tail of the loop (a great way to add subtle typos that will cause errors)? I think it also introduces a slippery slope to be encouraged to repeat yourself: if assigning the loop variable happens twice, you might decide to do something funny the 2:Nth time to avoid writing another loop, and that subtlety in loop variable assignment can be very easy to miss when reading code. There is no general solution I've seen to this prior to :=. Now, you can write something like `while line := f.readline()` and avoid repetition. I'm very happy to see this.
[0] https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
[1] https://lwn.net/Articles/757713/ https://lwn.net/Articles/757713/
[edit] fixed typos
- owlowlowls 7y ago>I'll add that := fixes something I truly hate: the lack of `do until` in Python, which strikes me as deeply un-Pythonic. Am I supposed to break out of `while True`? Am I supposed to set the variable before and at the tail of the loop (a great way to add subtle typos that won't cause errors)? This is relevant to what I've been doing in OpenCV with reading frames from videos! In tutorial examples on the web, you'll see exactly the sort of pattern that's outlined in the PEP 572 article. >line = f.readline() >while line: > ... # process line > line = f.readline() Just, replace readline() with readframe() and the like. So many off-by-one errors figuring out when exactly to break.
- kbd 7y agoFor sure. Walrus operator is "unnecessary" but is a clear improvement in the code that will use it.
- Aramgutang 7y agoThat example can also be tackled with Python's little-known feature of calling the built-in `iter` with a second argument: > for line in iter(f.readline, ''): > ... # process line See: https://docs.python.org/3/library/functions.html#iter https://docs.python.org/3/library/functions.html#iter
- jl2718 7y agoThis is useful, but two totally different functions with the same name distinguished only by the presence, not even the value of an unused argument. Where else does anything like this exist in the language? Seems problematic.
- dragonwriter 7y ago> This is useful, but two totally different functions with the same name distinguished only by the presence, not even the value of an unused argument. The sentinel argument is not unused. > Where else does anything like this exist in the language? In the narrow sense of “in the language” (builtins only), it's unique. There may be other examples in stdlib. That aside, functions that do a descriptively similar thing (i.e.,“build an iterator”) but where the details of how they do it differ significantly by aritt aren't weird among programming languages generally; don't see why it would be particularly problematic.
- Asooka 7y agoYou are supposed to write for x in iter(f.readline, ""): Or if you don't know what readline will return you can wrap it in your own lambda: for x in iter(lambda:f.readline() or None, None): There is a lot you can do with iter to write the kind of loops you want but it's not well known for some reason. It's a very basic part of the language people seem to overlook. Walrus does however let you write the slightly more useful while predicate(x:=whatever()): Which doesn't decompose easily into iter form.
- stefco_ 7y agoThis is a good solution! I don't directly use `iter` very often so I only remember it's simplicity part of the time. Sadly, this is not the idiom I see in most places. I will say, though, that I was not comfortable using iterators when I first learned python; walrus strikes me as easier to grok for a novice (one of the ostensible Python target demographics) than iter. I'll bet this is why this simple form is not idiomatic (though you're right, it should be).
- thomasahle 7y agoThe problem with `while line := f.readline():` is that it takes preasure of library writers. You should really just do `for line in f:`. If the library only has a `next` function, it needs to be fixed.
- masklinn 7y ago`f` might be iterable / iterator with completely different semantics than doing by-line iteration. And that might even be a good idea.
- thomasahle 7y agoIn this case it isn't though. And if it were, you could provide an `f.lines()` iterator. The code would be much nicer that way.