3 ms·
It's a controversial PEP https://www.python.org/dev/peps/pep-0572/ https://www.python.org/dev/peps/pep-0572/ which allows you to write Python like this: de
by est 8y ago
It's a controversial PEP https://www.python.org/dev/peps/pep-0572/ https://www.python.org/dev/peps/pep-0572/ which allows you to write Python like this:
def foo():
if n := randint(0, 3):
return n ** 2
return 1337
[(x, y, x/y) for x in input_data if (y := f(x)) > 0]
- ForHackernews 8y agoIck.
- kibibu 8y agoI've come around to it purely based on the application in list comprehensions.
- aviraldg 8y agoIt also seems include a special case for if/while that lets you do: def foo(): if randint(0, 3) as n: return n ** 2 return 1337 which looks a bit better to me.
- icebraining 8y agoI think that's a rejected alternative proposal, not part of this PEP.
- s3m4j 8y agohttps://www.python.org/dev/peps/pep-0572/#alternative-spellings https://www.python.org/dev/peps/pep-0572/#alternative-spelli...
- chombier 8y agoCan somebody comment on why is this PEP controversial?
- detaro 8y agoIt makes list expressions and some other things more powerful, but some feel the potential to create difficult-to-understand constructs with it is too high and the current ways of writing such code are clear enough.
- est 8y agoFor many people (including me) who learned Python the way that, in languages like C, the `if x=2` assignment combined with condition is an anti-pattern and prone to errors. This PEP solves very little problem, saves a few characters of code, but adds complexity to readability.
- ATsch 8y agoI don't think the controversy here is with the feature itself, more with the implementation. Many, me included, would have preferred to seen a different implementation of solutions to the same problems. Code starts becoming a lot harder to reason about when more than one state is mutated on the same line. The good design of Python makes this harder than in say C and I think this is a step in the wrong direction in that regard. The two real things this solves are checking for truthyness in an if and reusing values in a filterting comprehension. Instead of the syntax we have now that can be used anywhere, adds a whole new concept and feels kind of out-of-place, I would have much preferred a solution that can only be used in vetted places, doesn't add a new thing people need to learn and follows the style of the language For example, my preferred solution for `if` would have been: if thing() as t: print(t) Usage of `as` is already established by the `with` block [value for x in y if value where value = x * 2] The order is unfortunately a bit weird here, but there is no need to add the whole concept of a different type of assignment and this syntax will feel instantly recognizable to people familiar mathematical notation, which is where the existing list comprehension syntax comes from and so has been established as well.
- sametmax 8y agoI wanted "as" too. But the accepted operator has the benefit of integrating perfectly with type hints.
- sluukkonen 8y agoWould've making regular assignment an expression broken too much existing code?
- icebraining 8y agoProbably not, since expressions can already be statements. But that would allow dangerous code like "if a = 3", which I don't think the Python devs would want to allow.
- sametmax 8y agoIt's a voluntary design choice since the beginning of Python to avoid the very common mistake of doing: while continue = "yes": instead of: while continue == "yes": Those mistakes introduce bugs that are hard to spot because they don't cause an immediate error, linters can hardly help with them and even a senior can make them while being tired.
- bluecalm 8y agoI don't know about linters but GCC warns me about that every time I make that typo. They could just require parenthesis when assignment value is used as boolean.
- stfwn 8y agoThis immediately looks useful for things like: if foo := bar[baz]: bar[baz] += 1 return foo else: bar[baz] = 1 return 0 Where foo is a dict keeping track of multiple things, and a non-existing key (baz) is never an error but rather the start of a new count. Faster and more readable than if baz in list(bar.keys()): .... Similar to Swift’s ‘if let’, it seems.
- kelnos 8y agoFor stuff like that I'd just use `defaultdict`. That if/else tree then reduces to 2 lines total.
- stfwn 8y agoThat’s a good tip, thanks!
- antoinealb 8y agoAs pointed, you can use either a default dict or just simply, and [more pythonic](https://blogs.msdn.microsoft.com/pythonengineering/2016/06/29/idiomatic-python-eafp-versus-lbyl/ https://blogs.msdn.microsoft.com/pythonengineering/2016/06/2...): try: bar[baz] += 1 except KeyError: bar[baz] = 1 Also you can check if a key is in a dict simply by doing "if baz in bar" no need for "list(bar.keys())", which will be slow (temp object + linear scan) vs O(1) hashmap lookup.
- stfwn 8y agoThe error-catching method seemed too drastic to me before, but the article explains the LBYL vs. EAFP arugument quite well. Thanks! I should find a way to get more code reviews, I really enjoy learning these small nuggets of info.
- bb88 8y agoIt's also time saving since the hash lookup needs to be done at most 1, as well. GP has two lookups in the hash list.
- 8y ago
- i_do_not_agree 8y agoThis is horrible. It looks like ":=" is a comparison operator. The last line is dangerously close to Erlang list comprehensions: [ {X, Y, X/Y} || X <- Some_Function (), Y <- Some_Other_Function () ] And people bitch about Erlang syntax. Edit: "/" is the division operator
- mFixman 8y agoReminds me of the kind of hacks you would find in an old-school K&R book.