8 ms·
Despite controversy, walrus operator is going to be like f-strings. Before: "Why do we need another way to..." After: "Hey this is great". People are wtf-ing a
by kbd 7y ago
Despite controversy, walrus operator is going to be like f-strings. Before: "Why do we need another way to..." After: "Hey this is great".
People are wtf-ing a bit about the positional-only parameters, but I view that as just a consistency change. It's a way to write in pure Python something that was previously only possible to say using the C api.
- stefco_ 7y agof-strings are the first truly-pretty way to do string formatting in python, and the best thing is that they avoid all of the shortcomings of other interpolation syntaxes I've worked with. It's one of those magical features that just lets you do exactly what you want without putting any thought at all into it. Digression on the old way's shortcomings: Probably the most annoying thing about the old "format" syntax was for writing error messages with parameters dynamically formatted in. I've written ugly string literals for verbose, helpful error messages with the old syntax, and it was truly awful. The long length of calls to "format" is what screws up your indentation, which then screws up the literals (or forces you to spread them over 3x as many lines as you would otherwise). It was so bad that the format operator was more readable. If `str.dedent` was a thing it would be less annoying thanks to multi-line strings, but even that is just a kludge. A big part of the issue is whitespace/string concatenation, which, I know, can be fixed with an autoformatter [0]. Autoformatters are great for munging literals (and diff reduction/style enforcement), sure, but if you have to mung literals tens of times in a reasonably-written module, there's something very wrong with the feature that's forcing that behavior. So, again: f-strings have saved me a ton of tedium. [0] https://github.com/python/black https://github.com/python/black
- bulatb 7y ago> If `str.dedent` was a thing Have you looked at textwrap.dedent?
- stefco_ 7y agoYes! `textwrap.dedent` is great. On further reflection `wrap` is actually more useful for this kludge (see below). But my point is that that's a whole import for a kludge. Compare the f-string ideal (by my standards): raise ValueError("File exists, not uploading: " f"{filename} -> {bucket}, {key}") ...which is short enough that it's readable, and it's clear where exactly each variable is going. It's the single obvious solution, so much so that I don't spend a second thinking about it (very Pythonic!). Compare it to using `str.format` with the same continued indentation: raise ValueError(("File exists, not uploading: {filename} -> " "{bucket}, {key}").format(filename=filename, bucket=bucket, key=key)) Even this minimal example looks terrible! Remember that a lot of exceptions are raised within multiply-nested blocks, and then format pushes things farther to the right (while also ruining your automated string-literal concatenation, hence the extra parentheses), leaving very little room for the format arguments. You can use a more self-consistent and readable indentation strategy: raise ValueError( ( "File exists, not uploading: {filename} -> " "{bucket}, {key}" ).format(filename, bucket, key) ) This is unquestionably more pleasant to read than the former, but it's 3 times longer than the simple f-string solution, and I would argue it is not any more readable than the f-string for this simple example. My point with having a `str.wrap` builtin is that at least you could use the docstring convention of terminating multi-line strings on a newline, which would get rid of the string concatenation issues while leaving you a consistent (albeit diminished by the "wrap" call) amount of rightward room for the `format` args: raise ValueError("""File exists, not uploading: {filename} -> {bucket}, {key} """.dedent().format(filename=filename, bucket=bucket, key=key)) Maybe a little bit better than the first one, especially if you're writing a longer docstring and don't want to think about string concatenation. But still a kludge. You can use positional formatting to shorten things up, but the fundamental weakness of `str.format` remains.
- bpchaps 7y agoHere's a clean way to do that: str_fmt = "File exists, not uploading: {filename} -> {bucket}, {key}" fmt_vals = dict(filename=filename, bucket=bucket, key=key) raise ValueError(str_fmt.dedent().format(**fmt_vals))
- deleted 7y ago[deleted]
- lewiscollard 7y agoFor me, the hugs thing about f-strings was that invalid string format characters become a compile time error (SyntaxError). print('I do not get executed :)') f'{!}' File "stefco.py", line 2 f'{!}' ^ SyntaxError: f-string: empty expression not allowed This has the pleasing characteristic of eliminating an entire class of bug. :)
- heydenberk 7y agoI'd used f-string-like syntaxes in other languages before they came to Python. It was immediately obvious to me what the benefit would be. I've used assignment expressions in other languages too! Python's version doesn't suffer from the JavaScript problem whereby equality and assignment are just a typo apart in, eg., the condition of your while loop. Nonetheless, I find that it ranges from marginally beneficial to marginally confusing in practice.
- deleted 7y ago[deleted]
- fny 7y agoI love string interpolation! But this seems to take it to a bizarre level place just to save a few keystrokes. Seriously, how is f"{now=!s}" substantially better than f"now={str(now)}"? Ergonomically, I see little benefit for the added complexity.
- airstrike 7y agoReadability counts, though I agree Explicit is better than implicit. Special cases aren't special enough to break the rules, Although practicality beats purity.
- hermitdev 7y agoI agree that the simple examples don't show much benefit, but imagine if you had a really complex expression. I can see the value there.
- sammorrowdrums 7y agoIt really feels like it's very explicit at this point that you want to cast whatever value interpolated into your format string to a string... I don't want a type error for the most clear use case, in the same way I don't want one for print, because if I wanted a behaviour other than the basic string representation then I would still need to call something differently anyway. Given that explicit control of the __str__ method is also baked into the language it's also very clear what to expect. I like type errors when handling something like '1' + 1 because the JavaScript alternative is surprising and hides bugs. No surprises that a string formatter would coerce to string for me automatically (although I get that's maybe just personal feeling). I love the f strings, they have made my codebase cleaner and clearer. Definitely a pythonic win.
- ehsankia 7y agoWas the controversy really about the need for the feature? I thought most people agreed it was a great feature to have, and most of the arguments were about `:=` vs re-using `as` for the operator.
- linsomniac 7y agoI don't know in this case, but I do know that the Python community tends to have strong opinions about things. The := resulted in Guido stepping down, which I think is a good indicator that there wasn't agreement that it was "a great feature to have" and just down to syntax... :-(
- dual_basis 7y agoTo be fair, Guido stepped down because of the way the community reacted. "The straw that broke the camel’s back was a very contentious Python enhancement proposal, where after I had accepted it, people went to social media like Twitter and said things that really hurt me personally. And some of the people who said hurtful things were actually core Python developers, so I felt that I didn’t quite have the trust of the Python core developer team anymore." Source: https://www.infoworld.com/article/3292936/guido-van-rossum-resigns-whats-next-for-python.html https://www.infoworld.com/article/3292936/guido-van-rossum-r... Note that Guido also was in support of the walrus operator, it's not like he stepped down because he disagreed with it.
- darkpuma 7y agoIt's really disappointing that people could get so worked up, over what is essentially deciding which color to paint the shed, that they chase off the project founder. I wonder if there is any way for open source communities to effectively promote the "take a step back and remember what really matters in life" approach to conflict resolution.
- toyg 7y agoGuido wasn't chased off, he is still in the core group. He just isn't BDFL anymore -- which, from a certain point of view, might be the best of both worlds. As a long-time python user and small-time advocate, I felt the walrus was a really bad decision.
- linsomniac 7y agoI've literally been wanting something like the walrus operator since I first started using Python in '97. Mostly for the "m = re.match(x, y); if m: do_something()" sort of syntax.
- dual_basis 7y agoI mean, that isolated example doesn't really demonstrate the benefit of a walrus operator does it? You could have just written "if re.match(x, y): do_something()". If you re-used the result of computation within the if statement, I feel that would be a better example, eg. "m = re.match(x, y); if m: do_something(m)".
- linsomniac 7y agoTrue enough, as you point out I would be expecting to do_something with m. :-)
- deleted 7y ago[deleted]
- adito 7y agoI wonder if the controversial Go's error check function "try" proposal[0] will also be similar to this situation. [0]: https://github.com/golang/go/issues/32437 https://github.com/golang/go/issues/32437
- chasontherobot 7y agoThat was already cancelled.
- choppaface 7y agoWas the walrus operator really worth "The PEP 572 mess"? https://lwn.net/Articles/757713/ https://lwn.net/Articles/757713/ That post makes a few things very clear: * The argument over the feature did not establish an explicit measure of efficacy for the feature. The discussion struggled to even find relevant non-Toy code examples. * The communication over the feature was almost entirely over email, even when it got extremely contentious. There was later some face-to-face talk at the summit. * Guido stepped down.
- contravariant 7y agoIt may not have been a fair trade, but then it wasn't a trade in the first place. Those all seem to be problems with the process itself, meaning that it could have happened any time a contentious feature came up, this just happened to be the one to trigger the problem.
- choppaface 7y agoI agree that a mess looked (sadly) inevitable based upon that post and some of the other surrounding context. E.g. Guido citing Yoda conditions, how dumb that game can be, and getting ignored. But just because the feature shipped and design-by-committee is upon us doesn't mean we need to accept the outcome. Why couldn't there have been a more evolutionary path for this feature? For example, there is surely a way to write a prototype library to accomplish the same effect with slightly different syntax. (How about a single function `walrus(a, b)` that does what `:=` does?). Then let real user adoption drive the change. Maybe somebody will discover case statements from scala and want that instead. I hope the committee models some amount of their work after WG21. C++ hasn't evolved so effectively because some people were magic visionaries. For the past decade, C++ has mostly ridden on the proven success of boost. And skipped a lot of the parts of boost that suck.
- Scarblac 7y agoBy itself I agree, every now and then you write a few lines that will be made a little shorter now that := exists. But there's a long standing trend of adding more and more of these small features to what was quite a clean and small language. It's becoming more complicated, backwards compatibility suffers, the likelyhood your coworker uses some construct that you never use increases, there is more to know about Python. Like f-strings, they are neat I guess. But we already had both % and .format(). Python is becoming messy. I doubt this is worth that.
- vorticalbox 7y agothey should pick f and put depreciation warnings on the other two, python is getting messy.
- uranusjr 7y agoThey can’t just deprecate the other two; f-string’s nature precludes it from being used in situations where formatting needs to occur lazily, e.g. i18n. This is the same reason why other languages with string interpolation also keep a format method around, e.g. Swift’s String(format:). I guess you could argue that they should at least deprecate %-formatting, and this has indeed been raised multiple times, even prior to f-string’s introduction, but the power of Backwards Compatibility Gods are still strong there, for better or for worse.
- heavenlyblue 7y agoNothing stops one from evaluating f-strings lazily. They could simply return a format string with parameters captured instead of interpolated string.
- hjk05 7y agoThey could... but then they wouldn’t return the interpolated string, and they’d be just like using format, just saving the characters “.format” which ruins the exact thing people like about them.
- brummm 7y agoI think in certain situations the walrus operator will probably be useful. But it definitely makes code less legible, which makes me cautious. The only useful use case I have found so far is list comprehensions where some function evaluation could be reduced to only one execution with the walrus operator.
- kbd 7y ago> But it definitely makes code less legible, which makes me cautious. Disagree. In cases where it's useful it can make the code much clearer. Just yesterday I wrote code of the form: foos = [] foo = func(a,b,c,d) while foo: foos.append(foo) foo = func(a,b,c,d) With the walrus operator, that would just be: foos = [] while foo := func(a,b,c,d): foos.append(foo) Further, I had to pull out 'func' into a function in the first place so I wouldn't have something complicated repeated twice, so it would remove the need for that function as well.
- craigds 7y agoYep, I can't wait to use the walrus operator. I just tried it out (`docker run -it python:3.8.0b2-slim`) and I'm hooked already. Also, it's times like these I'm really glad docker exists. Trying that out before docker would have been a way bigger drama