+1 very useful also for me. Once in a while I have this exact
scenario. Not often enough to get annoyed, but often enough that it
would be nice to have.

On Tue, 28 Jul 2020 at 20:27, Noam Yorav-Raphael <noamr...@gmail.com> wrote:
>
> Hello,
>
> There's a simple function that I use many times, and I think may be a good 
> fit to be added to itertools. A function that gets an iterator, and if it has 
> exactly one element returns it, and otherwise raises an exception. This is 
> very useful for cases where I do some sort of query that I expect to get 
> exactly one result, and I want an exception to be raised if I'm wrong. For 
> example:
>
> jack = one(p for p in people if p.id == '1234')
>
> sqlalchemy already has such a function for queries: 
> https://docs.sqlalchemy.org/en/13/orm/query.html#sqlalchemy.orm.query.Query.one
>
> more-itertools has this exact function:
> https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.one
>
> Here is a simple implementation:
>
> def one(iterable):
>     it = iter(iterable)
>     try:
>         first = next(it)
>     except StopIteration:
>         raise ValueError("Iterator is empty")
>     try:
>         second = next(it)
>     except StopIteration:
>         return first
>     else:
>         raise ValueError("Iterator has more than one item")
>
> I brought this up on python-dev, but it should be discussed here.
> Here is the discussion:
> https://mail.python.org/archives/list/python-...@python.org/thread/D52MPKLIN4VEXBOCKVMTWAK66MAOEINY/
>
> Brett Cannon said that this idea has been brought up at least twice before. I 
> found:
> https://mail.python.org/archives/list/python-ideas@python.org/thread/FTJ6JRDTZ57HUVZ3PVIZV2NHU2NLAC4X/#RMWV3SNZ2N4KZLPKPIDE42H46QDEIVHE
>
> https://mail.python.org/archives/list/python-ideas@python.org/thread/REYDJFCXQNQG4SAWKELQMCGM77IZG47Q/#ITR2ILPVCKYR52U2D7RHGENASZTNVDHN
>
> The first thread hasn't reached any operative conclusion. The second thread 
> was very long, and seemed to focus mostly on another function, first(), that 
> doesn't check if there is more than one item. Joao S. O Bueno said that it 
> passed "general approval". I think that perhaps a new discussion, focused 
> just on one (no pun intended) function in the itertools module may reach a 
> conclusion.
>
> It was suggested that instead of an additional function, one can use iterator 
> unpacking:
>
> jack, = (p for p in people if p.id == '1234')
> or
> [jack] = (p for p in people if p.id == '1234')
>
> I still think that having a one() function would be useful, since:
> 1. I think it spells the intention more clearly. It is not symbols that you 
> need to understand their meaning in order to understand that I expect the 
> iterable to have exactly one item, it's spelled in code.
> 2. The exception would be easier to understand, since errors in tuple 
> unpacking usually mean something else.
> 3. The one() function allows you to use the result inside an expression 
> without assigning it to a variable. Therefore, I think it encourages writing 
> better code. It's very easy to write:
>     print([p for p in people if p.id == '1234][0])
> (which has the problem of not verifying the assumption that there's no more 
> than one result), and I find it easier to replace _[0] with one(_) than to be 
> required to name a new variable, and instead of having an operation on the 
> iterable, change the way I'm assigning to it.
>
> WDYT?
>
> Cheers,
> Noam
>
>
> _______________________________________________
> 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/6OLEL4XTUWXRI7ENODKEDOYFBRVDYKI7/
> Code of Conduct: http://python.org/psf/codeofconduct/



-- 
Kind regards,

Stefano Borini
_______________________________________________
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/FZGXJ36VUMU5XYVOSZR4AXV2FDSQLXEJ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to