[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-10 Thread Dom Grigonis
I like this. Something that I would use for sure.

I have used a lot of:

```
(value: None | object ) or default
```

, but I stopped for obvious reasons. However, I miss those days, when I was 
ignorant that this is not a good idea.

> On 11 Jul 2023, at 01:17, David Mertz, Ph.D.  wrote:
> 
> This is basically PEP 505 – None-aware operators 
> (https://peps.python.org/pep-0505/ ).
> 
> I've generally been opposed to that, but clearly some serious and smart 
> Pythonistas have supported it.  That PEP is a bigger lift than your 
> suggestion,  but correspondingly more general.
> 
> On Mon, Jul 10, 2023, 6:04 PM Jothir Adithyan  > wrote:
> Hi everyone,  
> 
> I would like to briefly present my idea regarding the `get` function commonly 
> used with dictionaries. When working with large amounts of JSON data, I often 
> encounter code that doesn't feel very Pythonic to me.  
> 
> Problem Statement:  
> 
> The `get` function allows chaining of method calls, which is quite useful 
> when working with dictionaries. It also has a convenient `default` parameter 
> that returns a default value if the key is not found in the dictionary. This 
> feature makes it safe and easy to use. However, problems arise when the 
> dictionary contains the key we are accessing, but the corresponding value is 
> `None`. In such cases, subsequent `get` calls fail because the `get` method 
> belongs to objects of type `dict` and not `None`. To address this, I propose 
> adding a new parameter to the `get` function or introducing a new function 
> called `get_or` that swiftly handles this issue. This new parameter, called 
> `arbitrary`, would accept an arbitrary value to be returned by subsequent 
> `get` calls in case the retrieved value of the key is `None`.  
> 
> Assumptions:  
> 
> The problem statement is based on a few assumptions:  
> - You prefer chaining `get` statements for cleaner code.  
> - You expect at least some of the `get` methods to return `None`.  
> - You want to avoid the hassle of using `try` and `except` for every `get` 
> chain.  
> 
> If you fall into the category of people who wish for a simpler way to work 
> with dictionaries and handle large amounts of data, I hope you can empathise 
> with this proposal.  
> 
> I have made a simple implementation by modifying the `get` method, which is 
> below this thread. I would appreciate your valuable input on this feature. 
> Before diving into coding, I want to make sure this is not a bad idea waiting 
> to reveal itself in the dark.  
> 
> Thank you for taking the time to read this thread. Your feedback is greatly 
> appreciated.  
> 
> Best regards,  
> Jothir Adithyan  
> 
> 
> 
> 
> **Runnable Version**  
> https://replit.com/@Adithyan71/GetOr 
> 
> 
> 
> **Code Samples.**  
> 
> ```  
> class PlayDict(dict):  
> def get_or(self, key, arbitrary=None, default=None):  
> if not self.__contains__(  
> key  
> ):  # case 1 the key does not exist hence the default value  
> return default  
> elif (  
> self[key] is None  
> ):  # case 2 key does exist but the value is None return the arb 
> value  
> return arbitrary  
> return self[key]  # case 3 the key is present and the value is not 
> None  
> 
> 
> import contextlib  
> parent_dict = PlayDict()  
> parent_dict['k1'] = None  
> parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested 
> dicts  
> 
> with contextlib.suppress(AttributeError):  
> result = parent_dict.get("k1", {}).get("child_key") # This will raise 
> AttributeError  
> 
> result = parent_dict.get_or("k1", default={}, arbitrary={}).get("child_key") 
> # This will work  
> 
> print(result)  
> ```
> ___
> 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/IELDCURRVQXCPGD4EPPLL7MYWJT4XHKV/
>  
> 
> Code of Conduct: http://python.org/psf/codeofconduct/ 
> 
> ___
> 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/4BCGPZ6TJFN4DCXIPR5I24ND7MOYPV5T/
> Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-10 Thread Dom Grigonis
This feels superfluous. Instead of creating new dict class I would propose 
either:
1. Not to have None values
  a) It is most likely possible to pre-delete all None values before you use 
the dict = {k: v for k, v in dict if v is not None}
  b) Not to create them in the first place (if it depends on you)
2. Or simply: (dict.get(‘k1’) or dict()).get(‘child_key')

> On 10 Jul 2023, at 22:18, Jothir Adithyan  wrote:
> 
> Hi everyone,  
> 
> I would like to briefly present my idea regarding the `get` function commonly 
> used with dictionaries. When working with large amounts of JSON data, I often 
> encounter code that doesn't feel very Pythonic to me.  
> 
> Problem Statement:  
> 
> The `get` function allows chaining of method calls, which is quite useful 
> when working with dictionaries. It also has a convenient `default` parameter 
> that returns a default value if the key is not found in the dictionary. This 
> feature makes it safe and easy to use. However, problems arise when the 
> dictionary contains the key we are accessing, but the corresponding value is 
> `None`. In such cases, subsequent `get` calls fail because the `get` method 
> belongs to objects of type `dict` and not `None`. To address this, I propose 
> adding a new parameter to the `get` function or introducing a new function 
> called `get_or` that swiftly handles this issue. This new parameter, called 
> `arbitrary`, would accept an arbitrary value to be returned by subsequent 
> `get` calls in case the retrieved value of the key is `None`.  
> 
> Assumptions:  
> 
> The problem statement is based on a few assumptions:  
> - You prefer chaining `get` statements for cleaner code.  
> - You expect at least some of the `get` methods to return `None`.  
> - You want to avoid the hassle of using `try` and `except` for every `get` 
> chain.  
> 
> If you fall into the category of people who wish for a simpler way to work 
> with dictionaries and handle large amounts of data, I hope you can empathise 
> with this proposal.  
> 
> I have made a simple implementation by modifying the `get` method, which is 
> below this thread. I would appreciate your valuable input on this feature. 
> Before diving into coding, I want to make sure this is not a bad idea waiting 
> to reveal itself in the dark.  
> 
> Thank you for taking the time to read this thread. Your feedback is greatly 
> appreciated.  
> 
> Best regards,  
> Jothir Adithyan  
> 
> 
> 
> 
> **Runnable Version**  
> https://replit.com/@Adithyan71/GetOr
> 
> 
> 
> **Code Samples.**  
> 
> ```  
> class PlayDict(dict):  
> def get_or(self, key, arbitrary=None, default=None):  
> if not self.__contains__(  
> key  
> ):  # case 1 the key does not exist hence the default value  
> return default  
> elif (  
> self[key] is None  
> ):  # case 2 key does exist but the value is None return the arb 
> value  
> return arbitrary  
> return self[key]  # case 3 the key is present and the value is not 
> None  
> 
> 
> import contextlib  
> parent_dict = PlayDict()  
> parent_dict['k1'] = None  
> parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested 
> dicts  
> 
> with contextlib.suppress(AttributeError):  
> result = parent_dict.get("k1", {}).get("child_key") # This will raise 
> AttributeError  
> 
> result = parent_dict.get_or("k1", default={}, arbitrary={}).get("child_key") 
> # This will work  
> 
> print(result)  
> ```
> ___
> 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/IELDCURRVQXCPGD4EPPLL7MYWJT4XHKV/
> Code of Conduct: http://python.org/psf/codeofconduct/

___
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/D4PFXZS7J27LYLXRSWTZVGCMGBYPOVL2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-10 Thread David Mertz, Ph.D.
This is basically PEP 505 – None-aware operators (
https://peps.python.org/pep-0505/).

I've generally been opposed to that, but clearly some serious and smart
Pythonistas have supported it.  That PEP is a bigger lift than your
suggestion,  but correspondingly more general.

On Mon, Jul 10, 2023, 6:04 PM Jothir Adithyan 
wrote:

> Hi everyone,
>
> I would like to briefly present my idea regarding the `get` function
> commonly used with dictionaries. When working with large amounts of JSON
> data, I often encounter code that doesn't feel very Pythonic to me.
>
> Problem Statement:
>
> The `get` function allows chaining of method calls, which is quite useful
> when working with dictionaries. It also has a convenient `default`
> parameter that returns a default value if the key is not found in the
> dictionary. This feature makes it safe and easy to use. However, problems
> arise when the dictionary contains the key we are accessing, but the
> corresponding value is `None`. In such cases, subsequent `get` calls fail
> because the `get` method belongs to objects of type `dict` and not `None`.
> To address this, I propose adding a new parameter to the `get` function or
> introducing a new function called `get_or` that swiftly handles this issue.
> This new parameter, called `arbitrary`, would accept an arbitrary value to
> be returned by subsequent `get` calls in case the retrieved value of the
> key is `None`.
>
> Assumptions:
>
> The problem statement is based on a few assumptions:
> - You prefer chaining `get` statements for cleaner code.
> - You expect at least some of the `get` methods to return `None`.
> - You want to avoid the hassle of using `try` and `except` for every `get`
> chain.
>
> If you fall into the category of people who wish for a simpler way to work
> with dictionaries and handle large amounts of data, I hope you can
> empathise with this proposal.
>
> I have made a simple implementation by modifying the `get` method, which
> is below this thread. I would appreciate your valuable input on this
> feature. Before diving into coding, I want to make sure this is not a bad
> idea waiting to reveal itself in the dark.
>
> Thank you for taking the time to read this thread. Your feedback is
> greatly appreciated.
>
> Best regards,
> Jothir Adithyan
>
>
>
>
> **Runnable Version**
> https://replit.com/@Adithyan71/GetOr
>
>
>
> **Code Samples.**
>
> ```
> class PlayDict(dict):
> def get_or(self, key, arbitrary=None, default=None):
> if not self.__contains__(
> key
> ):  # case 1 the key does not exist hence the default value
> return default
> elif (
> self[key] is None
> ):  # case 2 key does exist but the value is None return the arb
> value
> return arbitrary
> return self[key]  # case 3 the key is present and the value is not
> None
>
>
> import contextlib
> parent_dict = PlayDict()
> parent_dict['k1'] = None
> parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested
> dicts
>
> with contextlib.suppress(AttributeError):
> result = parent_dict.get("k1", {}).get("child_key") # This will raise
> AttributeError
>
> result = parent_dict.get_or("k1", default={},
> arbitrary={}).get("child_key") # This will work
>
> print(result)
> ```
> ___
> 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/IELDCURRVQXCPGD4EPPLL7MYWJT4XHKV/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
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/4BCGPZ6TJFN4DCXIPR5I24ND7MOYPV5T/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal for get_or function in Python dictionaries

2023-07-10 Thread Chris Angelico
On Tue, 11 Jul 2023 at 08:05, Jothir Adithyan  wrote:
> Assumptions:
>
> The problem statement is based on a few assumptions:
> - You prefer chaining `get` statements for cleaner code.
> - You expect at least some of the `get` methods to return `None`.
> - You want to avoid the hassle of using `try` and `except` for every `get` 
> chain.
>

The main assumption here is that None is a perfectly valid value in
your data, and should be equivalent to the key being omitted. I think
this is uncommon enough to be better done with custom code. But
fortunately, there's a really cool way to write that custom code, and
that's a path lookup - this is a sort of function that I've written in
a lot of these situations. Using your examples:

> import contextlib
> parent_dict = PlayDict()
> parent_dict['k1'] = None
> parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested 
> dicts
>
> with contextlib.suppress(AttributeError):
> result = parent_dict.get("k1", {}).get("child_key") # This will raise 
> AttributeError
>
> result = parent_dict.get_or("k1", default={}, arbitrary={}).get("child_key") 
> # This will work
>

I'd write it like this:

def lookup(basis, *keys, default=None):
for key in keys:
basis = basis.get(key)
if basis is None: return default
return basis

result = lookup(parent_dict, "k1", "child_key")

This quite tidily expresses the intent ("delve into this dictionary
and follow this path, returning None if there's nothing there"), and
is compact, with no repetition. It's a relatively short helper
function too, and easy to change into other forms. For example, here's
another version that I use, which guarantees to always return a
dictionary:

def lookup(basis, *keys):
for key in keys:
if key not in basis: basis[key] = {}
basis = basis[key]
return basis

Etcetera. Flexible and very handy.

ChrisA
___
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/UIIRM2KIRBUMGHKKZNUU233WWOLSUXIB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Proposal for get_or function in Python dictionaries

2023-07-10 Thread Jothir Adithyan
Hi everyone,  
  
I would like to briefly present my idea regarding the `get` function commonly 
used with dictionaries. When working with large amounts of JSON data, I often 
encounter code that doesn't feel very Pythonic to me.  
  
Problem Statement:  
  
The `get` function allows chaining of method calls, which is quite useful when 
working with dictionaries. It also has a convenient `default` parameter that 
returns a default value if the key is not found in the dictionary. This feature 
makes it safe and easy to use. However, problems arise when the dictionary 
contains the key we are accessing, but the corresponding value is `None`. In 
such cases, subsequent `get` calls fail because the `get` method belongs to 
objects of type `dict` and not `None`. To address this, I propose adding a new 
parameter to the `get` function or introducing a new function called `get_or` 
that swiftly handles this issue. This new parameter, called `arbitrary`, would 
accept an arbitrary value to be returned by subsequent `get` calls in case the 
retrieved value of the key is `None`.  
  
Assumptions:  
  
The problem statement is based on a few assumptions:  
- You prefer chaining `get` statements for cleaner code.  
- You expect at least some of the `get` methods to return `None`.  
- You want to avoid the hassle of using `try` and `except` for every `get` 
chain.  
  
If you fall into the category of people who wish for a simpler way to work with 
dictionaries and handle large amounts of data, I hope you can empathise with 
this proposal.  
  
I have made a simple implementation by modifying the `get` method, which is 
below this thread. I would appreciate your valuable input on this feature. 
Before diving into coding, I want to make sure this is not a bad idea waiting 
to reveal itself in the dark.  
  
Thank you for taking the time to read this thread. Your feedback is greatly 
appreciated.  
  
Best regards,  
Jothir Adithyan  
  

  

**Runnable Version**  
https://replit.com/@Adithyan71/GetOr

  

**Code Samples.**  
  
```  
class PlayDict(dict):  
    def get_or(self, key, arbitrary=None, default=None):  
        if not self.__contains__(  
            key  
        ):  # case 1 the key does not exist hence the default value  
            return default  
        elif (  
            self[key] is None  
        ):  # case 2 key does exist but the value is None return the arb value  
            return arbitrary  
        return self[key]  # case 3 the key is present and the value is not None 
 
  
  
import contextlib  
parent_dict = PlayDict()  
parent_dict['k1'] = None  
parent_dict['k2'] = {"child_key": "val"} # Parent dict can contain nested dicts 
 
  
with contextlib.suppress(AttributeError):  
    result = parent_dict.get("k1", {}).get("child_key") # This will raise 
AttributeError  
  
result = parent_dict.get_or("k1", default={}, arbitrary={}).get("child_key") # 
This will work  
  
print(result)  
```
___
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/IELDCURRVQXCPGD4EPPLL7MYWJT4XHKV/
Code of Conduct: http://python.org/psf/codeofconduct/