Em sex, 3 de jul de 2020 11:37, Kyle Lahnakoski <klahnako...@mozilla.com> escreveu:
> > On 2020-06-27 09:34, Daniel. wrote: > > When I need to traverse nested dicts, is a common pattern to do > > > > somedict.get('foo', {}).get('bar', {}) > > > > But there is no such equivalent for arrays, wouldn't be nice if we can > > follow > > > > somedict.get('foo', {}).get('bar', []).get(10) ... ? > > > > What do you think? > > > I would use this. I do something similar already, albeit as a set of > classes that wrap around Python `dict` and `list` to provide the > null-safe access. > > to_data(somedict).foo.bar[10] > Yeah, I just get the same idea but using rshift to emulate safe access infix operator somedict >> get('foo') Since I can't add behavior to exiting classes in python, I resort to things like that to "emulate" method calls. You can think somelist >> get(0) as somelist.get(0) So I don't have to deal with an extra type in translation when sending data back to a third party library > Specifically, I wrap `list` in `FlatList`, which will return `Null` > (null-safe version of `None`) instead of raising and IndexError. This > allows math on indexes without concern for corner cases, and makes > window functions easier to write: > > | my_list = FlatList(my_list) > | deltas = [] > | for i, this_week in enumerate(my_list): > | last_week = my_list[i-7] > | deltas.append(this_week - last_week) > > by avoiding exception handling, code is simplified, and procedures > simplify to functions. Instead of code that constructs a list; the code > reads as a list definition: > > | deltas = [ > | this_week - last_week > | for my_list in [FlatList(my_list)] > | for i, this_week in enumerate(my_list) > | for last_week in [my_list[i-7]] > | ] > Yeah I feel that try/catch add lots of noise to null present code. We always tend to abstract null handling in some way and each one come up with its own implementation. The list.get method has the advatage, as Alex said, of already being a common dialect with dicts. If dict.get didn't exist I probably wouldn't even asking for it, but every time that I need to handle json and I start with dict.get and hit an list I end up with an wrapper over IndexError. try/catch are nice for medium blocks for single lines they are too many noise, you have 3 lines of error handling for one of real logic. (But you can wrap that in a function). Yeah, then you have to shift the reading flow to that function. When you see dict.get, you know what's happening, it's just straight to the point. If we had the same method for list, our codes may look similar while solving almost the same problem (handling null). But since there isn't we create whole new abstractions that are completely different. > > please forgive me: where `for x in [y]` can be read as `x=y` (I am > still hesitant to use `:=`) > > There are detriments to using a set of null-safe objects: > > 1. data structures can be polluted with a combination of null-safe > objects and regular Python structures > > 2. with null-safe code, there are more nulls and it seems EVERYTHING > must be null-safe, including arithmetic (notice null-safe subtraction > above) > It all depends of you're propagating None or not. And not if your code is None aware or not. But yeah, none aware code are easier to follow and write, at last for me, because the missing value handling is abstrated. But still, I'm not talking about to add a method to propagate more Nones, no, even if this is what .get does. I'm asking for something that can be used in conjunction with dict.get to deal with nested data in an elegant and idiomatic form so we stop to ac-hoc abstracting IndexError and start to use a common idiom. Another simple use case that I use this is to have give simple scripts a default command line argument, like try: arg = sys.argv[1] except IndexError: arg = default Or if len(sys.argv) >= 2: arg = sys.argv[1] else: arg = default Which would be rewritten as arg = sys.argv.get(1, default) I'm hopeful that there are more people with other uses case out there that didn't see the thread yet > 3. runs slower; all the null-safe checks dominate my profiler time. > > > I would be nice if Python had a series of null-safe operators. Until > then, `list.get` would eliminate my extra object creation: > I would really love it too, I was expecting to drop this in favor of pep 505 but as Alex pointed, it wouldn't handle IndexError case, so even with null operators we will be still having to handle with a except block > > | deltas = [ > | this_week - (last_week or 0) > | for i, this_week in enumerate(my_list) > | for last_week in [my_list.get(i-7)] > | ] > > Although we see additional null-checks required (as #2 states). > > _______________________________________________ > Python-ideas mailing list -- python-ideas@python.org > To unsubscribe send an email to python-ideas-le...@python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ > Message archived at > https://mail.python.org/archives/list/python-ideas@python.org/message/UKU2PN43EQZ4ZWVDFXR6XO4ST3WBCNVE/ > Code of Conduct: http://python.org/psf/codeofconduct/ Regards > >
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/5DF6VHFPJLBIRRRWI4S7EQWW5CY54RV7/ Code of Conduct: http://python.org/psf/codeofconduct/