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/

Reply via email to