4 ms·
I've added an edit to my comment to help you through the logical jump, and in the rest of this comment I write it out explicitly. So, my reasoning is that I su
by logicallee 8y ago
I've added an edit to my comment to help you through the logical jump, and in the rest of this comment I write it out explicitly.
So, my reasoning is that I surely must end up liking it, if it ended up accepted despite breaking every rule in the book. They wouldn't accept it for something that wasn't incredibly useful. My first impression is that it's incredibly ugly, unpythonic, and unreadable (what does it even do?), and this is pretty "obvious".
So arguing based on what I know about Python design philosophy, and the fact that this has been so deeply discussed, it must be absolutely fantastic.
I wouldn't think it's great (if you gave me the syntax), I'd recite all the Python Values it breaks -
https://en.m.wikipedia.org/wiki/Zen_of_Python https://en.m.wikipedia.org/wiki/Zen_of_Python :
- Beautiful is better than ugly.
Nope, this is very ugly.
- Simple is better than complex.
Nope, this isn't simple.
- Flat is better than nested.
Nope, this explicitly exists to let you nest something.
- Sparse is better than dense.
Nope, this explicitly exists to make code denser.
- Readability counts.
Nope: this is literally not readable. You don't know what the first code example I gave does. Normally with Python you just "write pseudocode and make sure you indent it properly."
- Special cases aren't special enough to break the rules.
This is a special case.
but here we get to the next rule, which trumps ALL of the above:
Although practicality beats purity.
- There should be one—and preferably only one—obvious way to do it.
This is broken, as now you can do it on two lines or one line.
- If the implementation is hard to explain, it's a bad idea.
It's kind of hard to explain, look at all our comments.
- If the implementation is easy to explain, it may be a good idea.
This isn't the case here.
I will grant that this is extremely explicit syntax. In this sense it is MUCH better than overloading = based on different contexts or something. As I mentioned above, anyone who sees := knows that it's a "known unknown" -- WTF is this?
So we are left with a single solitary Pythonic value:
- Practicality beats purity.
Based on this alone, I reason that it must be great to have been accepted. It must be extremely practical. It must save a lot of time.
I am quite disposed to thinking (honestly!) that it must be pretty darn great. It will save a lot of time.
There's no way that it made it into the language if it didn't, since it's so obviously ugly and unpythonic.
But practicality beats purity. I'm sure I'll love it!
- garettmd 8y agoJust yesterday I was thinking I would like to have something like this. I didn't know that this type of feature had a name, nor did I know what it would/could look like, but now that I see it in this PEP, it looks awesome to me. Yes, it does also look like something that could be greatly abused. But I think the way to temper that is to add guidelines for it (for linting) and to not bring this feature up for learners until they've reached a more advanced level (which I figure will likely happen, as it will be new for most experienced Python coders for a while)
- abuckenheimer 8y agoI don't know the Kirill Balunov example is pretty beautiful/simple/flat/readable if reductor := dispatch_table.get(cls): rv = reductor(x) elif reductor := getattr(x, "__reduce_ex__", None): rv = reductor(4) elif reductor := getattr(x, "__reduce__", None): rv = reductor() else: raise Error("un(shallow)copyable object of type %s" % cls) especially when you compare it to the existing implementation: reductor = dispatch_table.get(cls) if reductor: rv = reductor(x) else: reductor = getattr(x, "__reduce_ex__", None) if reductor: rv = reductor(4) else: reductor = getattr(x, "__reduce__", None) if reductor: rv = reductor() else: raise Error("un(shallow)copyable object of type %s" % cls)
- carapace 8y agoNah, write a little gadget: def f(F, *args): f.reductor = F(*args) return bool(f.reductor) if f(dispatch_table.get, cls)): rv = f.reductor(x) elif f(getattr, x, "__reduce_ex__", None): rv = f.reductor(4) elif f(getattr, x, "__reduce__", None): rv = f.reductor() else: raise Error("un(shallow)copyable object of type %s" % cls) Same pattern works for re.match objects. Once you abstract the patterns you can drive towards data-driven code: K = ( (dispatch_table.get, (cls,), (x,)), (getattr, (x, "__reduce_ex__", None), (4,)), (getattr, (x, "__reduce__", None), ()), ) for F, a, b in K: reductor = F(*a) if reductor: rv = reductor(*b) break else: raise Error("un(shallow)copyable object of type %s" % cls) Syntax is the enemy, never substitute syntax for thought.