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

2023-07-15 Thread Dom Grigonis
I am well aware of that.

I just argue that it is not very pleasant to read.

Personally, I am not a big user of it.

C’s although maybe doesn’t have words to read, but is much more pleasant in 
both conciseness and logical sequence.

Maybe it is not a big issue for others, but if C’s style conditional expression 
existed, it would significantly change the way I write things.

So just checking. :)

> On 16 Jul 2023, at 00:06, Paul Moore  wrote:
> 
> On Sat, 15 Jul 2023 at 21:09, Dom Grigonis  > wrote:
> So I would vote for something similar to:
>> result = bar is None ? default : bar
> 
> 
> result = default if bar is None else bar
> 
> Python has a conditional expression already.
> Paul 

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


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

2023-07-15 Thread Paul Moore
On Sat, 15 Jul 2023 at 21:09, Dom Grigonis  wrote:

> So I would vote for something similar to:
>
> result = bar is None ? default : bar
>
>
result = default if bar is None else bar

Python has a conditional expression already.
Paul
___
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/3BKGZIIIP6HRMR52BXRYRMEPFYKBPRIW/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2023-07-15 Thread Dom Grigonis
Just to add. I haven’t thought about evaluation. Thus, to prevent evaluation of 
unnecessary code, introduction of C-style expression is needed anyways:
> 1. result = bar is None ? default : bar

The below would have to evaluate all arguments, thus not achieving benefits of 
PEP505.
> 2. result = ifelse(bar is None, default, bar)


So I would vote for something similar to:
> result = bar is None ? default : bar


Where default and bar is only evaluated if needed. Although not to the extent 
as initially intended, it would offer satisfiable solutions to several 
proposals.


> On 15 Jul 2023, at 22:37, Dom Grigonis  wrote:
> 
> def fu(bar, default=1):
> bar = bar or default
> return bar
> 
> print(fu(None))   # 1 - as expected
> print(fu(2))  # 2 - as expected
> print(fu(0))  # 1 - not as expected
> 
> class A:
> def __bool__(self):
> return False
> 
> print(fu(A()) # 1 - not as expected
> 
> So it only works if ALL possible bar values are limited to those that 
> evaluate to True on truth test. And even if I have such cases, when this is 
> the case, I restrain from doing this for the sake of consistency of coding 
> style and to eliminate risk if I ever decide to introduce new input options 
> that do not comply with this restriction. Just to be on the safe side.
> 
> Obviously, one could do:
> def fu(bar, default=1):
> bar = bar if bar is not None else default
> return bar
> But not having lengthy, hard to read expressions to do such a simple thing is 
> the key here isn’t it?
> 
> So my latest resolve for such cases is simply:
> def fu(bar, default=1):
> if bar is None:
> bar = default
> return bar
> So 2 lines instead of 1, but easy to read, risk-free simple code.
> 
> In case of class construction, I suffer 1 extra assignment here:
> def __init__(self, bar, default=1):
> self.bar = bar
> if bar is None:
> self.bar = default
> Which I don’t like! Extra assignment is not ideal. Of course I could use:
> def __init__(self, bar, default=1):
> if bar is None:
> self.bar = default
> else:
> self.bar = bar
> Or the 1-line if-else, but (to repeat myself) these 2 don’t read nicely and 
> lack aesthetics for such a simple case as this.
> 
> IMO, what could probably be a good (time tested and convenient) solution is 
> to introduce something similar to C-style, low-level `ifelse` expression.
> 
> string result = (time < 18) ? "Good day." : "Good evening.”;
> 
> My personal opinion is that 1-line pythonic if-else expression lacks pythonic 
> aesthetics.
> 
> The PEP505 looks nice, but it is mostly concerned with `None`, which I IMO is 
> the reason it didn’t go through. It’s the same as with sentinels: 
> https://peps.python.org/pep-0661/ 
> 
> The proposal is too narrow and specific, to be implemented in core python. In 
> other words, it only solves one corner case, but not the root issue. My 
> solution to PEP661 was to use `unittest.sentinel` so I can define my own 
> `None` alternatives.
> 
> Now, if PEP505 was accepted, then it would only work for `None`, but not for 
> user-defined sentinels, meaning it is not a good solution either - something 
> more general is needed. What I think could potentially be optimal is either:
> 1. result = bar is None ? default : bar
>   However, in this case, new operator had to be introduced instead of 
> “:”, which I am sure would arise many discussions. Although, I think this is 
> a very elegant expression
> 2. result = ifelse(bar is None, default, bar)
>   Having such well-optimised builtin in core python, would also be a good 
> solution without introduction of any new operators.
> 
> Now, this doesn’t directly solve your initial proposal:
> ifelse(dict.get('key') is None, {}, dict.get('key')).get('child_key')
> However, then it could be easier to define a new method when subclassing 
> `dict` or `UserDict`
> from unittest.sentinel import Sentinel
> NotGiven = Sentinel.NotGiven
> 
> class PlayDict(dict):
> def get_or(self, key, default=NotGiven, arbitrary=None):
> value = self.get(key, default)
> return value is NotGiven ? arbitrary : value
> # OR
> return ifelse(value is NotGiven, arbitrary, value)
> Whether this is included in core-python or not is another matter. It is not 
> as elegant as proposal in PEP505, but it is not limited to `None` sentinel, 
> while making use of nicely-read 1-liner.
> 
> So IMO, a more elegant if-else 1-liner is potentially a happy middle, which 
> would cover many different cases, although not as elegantly as PEP505.
> 
> 
>> On 15 Jul 2023, at 21:07, Jothir Adithyan > > wrote:
>> 
>> Dom Grigonis wrote:
>>> 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 

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

2023-07-15 Thread Dom Grigonis
> I understand your perspective, but the fact is that this makes the code 
> lengthier and adds an extra step to what I am already trying to do. 
> Additionally, if I understand correctly, I could implement a built-in method 
> as a function that takes in the key and uses a try-except block to get the 
> value or return None, which is essentially Python's way of handling missing 
> values (similar to get()).
> I proposed this solution because Python is widely used by many people and 
> organizations for web scraping and API integrations, where None values are 
> often expected and need to be handled efficiently. I believe this could be a 
> valuable addition, but please correct me if I'm wrong.
I think adding an extra method is the only reasonable solution anyways. 
Modifying `dict.get` even if not breaking any existing functionality, would 
result in decreased performance across the whole landscape of code that uses 
`get`, which doesn’t seem like a big cost, but from experience, dictionary 
methods do tend to become bottlenecks in highly-optimised python code (which is 
often the case given the obvious disadvantage of interpreted language).

So the only question here is whether to add an extra method in python core. 
Such as you did e.g. `get_if`, or leave it to the user. If left to the user, 
then maybe it is possible to solve several issues at the same time by providing 
elegant, optimised & flexible one-liners (see my other e-mail) to do such 
thing, leaving implementation details to the user.

You are concerned about `None`, maybe someone else is concerned about some 
other value that he wishes to treat as non-valid. Permutations are endless in 
value-space and depth.

Implementing and especially changing already existing functionality in 
core-python requires consideration of many perspectives, which I, myself, do 
not have enough, so this is just my opinion.

But from what I have gathered from experience analysing others' and my own 
suggestions in this group, the one you are proposing (at least taken at it’s 
face value) is too limiting, and potentially too invasive for too little 
benefit in relation to how close to `python’s metal` it is.


> On 15 Jul 2023, at 20:57, Jothir Adithyan  wrote:
> 
> Dom Grigonis wrote:
>> 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 adithyanjot...@gmail.com 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__(  
>>>  

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

2023-07-15 Thread Chris Angelico
On Sun, 16 Jul 2023 at 04:07, Jothir Adithyan  wrote:
>
> Chris Angelico wrote:
> > On Tue, 11 Jul 2023 at 08:05, Jothir Adithyan adithyanjot...@gmail.com 
> > 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
> Hey Chris, thank you for your time and insight.
>
> I've thought about this for some time, and I believe that adding this feature 
> could indeed be a useful and concise helper for many Python users, especially 
> for API integrations and web scraping where encountering None values is quite 
> common. Do you think it would be feasible to modify the existing get function 
> to include a new parameter or perhaps introduce a new function altogether?
>
> I'm trying to understand why this idea may not be considered favorable. What 
> are the reasons for not having this feature? What makes the current approach 
> better than having this additional functionality?
>

The reason it's not a good fit for the language itself is that there
are lots of small variations. I gave you one other slight variant in
my example, and there are myriad other small differences that could
show up. So it's best for it to be part of your own toolkit. I would
strongly recommend giving the "path lookup" function style a try; it's
actually way more expressive than chained lookups, in the situations
that it's appropriate to.

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


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

2023-07-15 Thread Dom Grigonis
def fu(bar, default=1):
bar = bar or default
return bar

print(fu(None))   # 1 - as expected
print(fu(2))  # 2 - as expected
print(fu(0))  # 1 - not as expected

class A:
def __bool__(self):
return False

print(fu(A()) # 1 - not as expected

So it only works if ALL possible bar values are limited to those that evaluate 
to True on truth test. And even if I have such cases, when this is the case, I 
restrain from doing this for the sake of consistency of coding style and to 
eliminate risk if I ever decide to introduce new input options that do not 
comply with this restriction. Just to be on the safe side.

Obviously, one could do:
def fu(bar, default=1):
bar = bar if bar is not None else default
return bar
But not having lengthy, hard to read expressions to do such a simple thing is 
the key here isn’t it?

So my latest resolve for such cases is simply:
def fu(bar, default=1):
if bar is None:
bar = default
return bar
So 2 lines instead of 1, but easy to read, risk-free simple code.

In case of class construction, I suffer 1 extra assignment here:
def __init__(self, bar, default=1):
self.bar = bar
if bar is None:
self.bar = default
Which I don’t like! Extra assignment is not ideal. Of course I could use:
def __init__(self, bar, default=1):
if bar is None:
self.bar = default
else:
self.bar = bar
Or the 1-line if-else, but (to repeat myself) these 2 don’t read nicely and 
lack aesthetics for such a simple case as this.

IMO, what could probably be a good (time tested and convenient) solution is to 
introduce something similar to C-style, low-level `ifelse` expression.

string result = (time < 18) ? "Good day." : "Good evening.”;

My personal opinion is that 1-line pythonic if-else expression lacks pythonic 
aesthetics.

The PEP505 looks nice, but it is mostly concerned with `None`, which I IMO is 
the reason it didn’t go through. It’s the same as with sentinels: 
https://peps.python.org/pep-0661/ 

The proposal is too narrow and specific, to be implemented in core python. In 
other words, it only solves one corner case, but not the root issue. My 
solution to PEP661 was to use `unittest.sentinel` so I can define my own `None` 
alternatives.

Now, if PEP505 was accepted, then it would only work for `None`, but not for 
user-defined sentinels, meaning it is not a good solution either - something 
more general is needed. What I think could potentially be optimal is either:
1. result = bar is None ? default : bar
However, in this case, new operator had to be introduced instead of 
“:”, which I am sure would arise many discussions. Although, I think this is a 
very elegant expression
2. result = ifelse(bar is None, default, bar)
Having such well-optimised builtin in core python, would also be a good 
solution without introduction of any new operators.

Now, this doesn’t directly solve your initial proposal:
ifelse(dict.get('key') is None, {}, dict.get('key')).get('child_key')
However, then it could be easier to define a new method when subclassing `dict` 
or `UserDict`
from unittest.sentinel import Sentinel
NotGiven = Sentinel.NotGiven

class PlayDict(dict):
def get_or(self, key, default=NotGiven, arbitrary=None):
value = self.get(key, default)
return value is NotGiven ? arbitrary : value
# OR
return ifelse(value is NotGiven, arbitrary, value)
Whether this is included in core-python or not is another matter. It is not as 
elegant as proposal in PEP505, but it is not limited to `None` sentinel, while 
making use of nicely-read 1-liner.

So IMO, a more elegant if-else 1-liner is potentially a happy middle, which 
would cover many different cases, although not as elegantly as PEP505.


> On 15 Jul 2023, at 21:07, Jothir Adithyan  wrote:
> 
> Dom Grigonis wrote:
>> 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. david.me...@gmail.com wrote:
>>> This is basically PEP 505 – None-aware operators 
>>> (https://peps.python.org/pep-0505/ 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 >> mailto:adithyanjot...@gmail.com> 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 

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

2023-07-15 Thread Jothir Adithyan
Dom Grigonis wrote:
> 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. david.me...@gmail.com wrote:
> > This is basically PEP 505 – None-aware operators 
> > (https://peps.python.org/pep-0505/ 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  > mailto:adithyanjot...@gmail.com> 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 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 
> > mailto:python-ideas@python.org
> > To unsubscribe send an email to python-ideas-le...@python.org 
> > mailto:python-ideas-le...@python.org
> > https://mail.python.org/mailman3/lists/python-ideas.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/IELDCU...
> >  
> > https://mail.python.org/archives/list/python-ideas@python.org/message/IELDCURRVQXCPGD4EPPLL7MYWJT4XHKV/
> > Code of Conduct: http://python.org/psf/codeofconduct/ 
> > 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/4BCGPZ...
> > Code of Conduct: 

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

2023-07-15 Thread Jothir Adithyan
Chris Angelico wrote:
> On Tue, 11 Jul 2023 at 08:05, Jothir Adithyan adithyanjot...@gmail.com 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
Hey Chris, thank you for your time and insight.

I've thought about this for some time, and I believe that adding this feature 
could indeed be a useful and concise helper for many Python users, especially 
for API integrations and web scraping where encountering None values is quite 
common. Do you think it would be feasible to modify the existing get function 
to include a new parameter or perhaps introduce a new function altogether?

I'm trying to understand why this idea may not be considered favorable. What 
are the reasons for not having this feature? What makes the current approach 
better than having this additional functionality?
___
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/JLYNXVVR6FYG2QB4ACWJBU3M3I3YMWQO/
Code of Conduct: http://python.org/psf/codeofconduct/


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

2023-07-15 Thread Jothir Adithyan
Dom Grigonis wrote:
> 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 adithyanjot...@gmail.com 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/IELDCU...
> > Code of Conduct: http://python.org/psf/codeofconduct/
> >

I understand your perspective, but the fact is that this makes the code 
lengthier and adds an extra step to what I am already trying to do. 
Additionally, if I understand correctly, I could implement a built-in method as 
a function that takes in the key and uses a try-except block to get the value 
or return None, which is essentially Python's way of handling missing values 
(similar to get()).

I proposed this solution because Python is widely used by many people and 
organizations for web scraping and API integrations, where None values are 
often expected and need to be handled efficiently. I believe this could be a 
valuable addition, but please correct me if I'm wrong.
___
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