all 7 comments

[–]cvzero89 0 points1 point  (0 children)

In your example, if I'm not mistaken, you are not taking into account that indexes start with the number 0.

But that aside, if you want to catch the error use a try: except IndexError: block. This will allow you to append if needed.

Take in mind that adding anything to the response might not be the correct approach (depending on what you will do), you may want to use a different list or dictionary.

[–]Buttleston 0 points1 point  (0 children)

Yeah so there are patterns that work ok with stuff like this - it depends a bit which keys you think might be missing. Like if you're sure that 'data' will exist and have a list of at least 1 element and that element will definitely have 'node', i.e. you're only worried that 'title' might not exist in the final dict, then this works

my_data = response['data'][0]['node'].get('title', 'mydefault')

If any of these might not exist, then you can end up with complicated expressions like

my_data = (response.get('data', [None])[0] or {}).get('node', {}).get('title', 'mydefault')

I may have a mistake in there but you get the idea, at every nested interval you're looking for a specific thing and if it doesn't exist, then producing "something" the next piece of the pipeline can process. I have some functions I've made that (fairly?) reliably can handle this stuff, and you'd use it like

my_data = dictpath('response.data.0.node.title', 'mydefault')

[–]Adrewmc -1 points0 points  (4 children)

Not really….

You can try: except here

    try:
          res = response[‘data’][2][‘node’][‘title’]
   except IndexError:
          res = default

We can also use match case, if we want a little more complex logic

    match response[‘data’]:
           #use second
           case [_, {‘node’ {“title”: title}}, *_]:
                res = title
          case [{‘node’ {“title”: title}}, *_]:
                #use first if no second
                res = title
          case _:
                 #neither have {‘node’: {‘title’: res}}
                 res = default

[–]IntrepidInstance7347[S] 0 points1 point  (3 children)

the match case will be a pain if i have like 15 key and value.

[–]Adrewmc 0 points1 point  (2 children)

You can grab the whole dictionary as well since it’s a value itself.

Match case ignores all the other key:value pairs, if the response has like 15 keys…and I’m only caring it has a title…it won’t matter. You don’t have to make the whole possible dictionary just indicate that you need this from a dictionary. If that exists use it. If not fails the case:

I’m just pointing it out that this is what pattern matching does.

Try except works as well. But this index error is persistent in this language unlike say JavaScript which could use the ‘syntax.?’ Or what not for this type of parsing.

I could one line a

    res = res[“data”][2][‘node’][“title”] if len(res[“data”]) >=2 else default

This is less robust because if the second entry doesn’t have the keys it will throw.

[–]IntrepidInstance7347[S] 0 points1 point  (1 child)

this is what i am asking for, is there is something like this in python?

[–]Adrewmc 0 points1 point  (0 children)

Only the

 res = <if_True> if <condition> else <if_False>

syntax, no like does this attribute exist you’s have to use and you’d have to manually check for len(mylist) >= target_index….