I have encountered plenty of uses for first(), usually the argument is a list or even a dict or set that’s already computed — for sets, it’s common that it’s known there’s only one element, the question is how to get that element.
On Thu, Dec 5, 2019 at 14:28 Andrew Barnert via Python-ideas < python-ideas@python.org> wrote: > On Dec 5, 2019, at 13:43, Juancarlo Añez <apal...@gmail.com> wrote: > > > > I just found this code: > > def get_product_item(jsonld_items): > for item in jsonld_items: > if item['@type'] == 'Product': > return item > else: > return {} > > > My argument is that the intent is clearer in: > > def get_product_item(jsonld_items): > return first((item for item in jsonld_items if item['@type'] == > 'Product'), {}) > > > There’s already a first_true in the recipes that does the filtering and > firsting together. > > Of course there’s the usual issue about filter vs. genexpr when your > predicate is naturally an in-line expression rather than a function, but > otherwise: > > from more_itertools import first_true > > def get_product_item(jsonId_items): > return first_true(jsonId_items, lambda item: item['@type'] == > 'Product', {}) > > Or even: > > get_product_item = partial(first_true, pred=lambda item: item['@type'] > == 'Product', default={}) > > I think in this case, because of the expression-vs.-lambda issue, I’d > write it with first and a genexpr if we had both. But a lot of itertoolsy > code is full of lambdas and partials like this (to call filter and map, use > as groupby and unique keys, etc.), and often the condition is something > you’ve already wrapped up as a function in the first place, so I’m not sure > how generally that applies without more examples. > > As a reminder, first()'s definition in Python is: > > def first(seq, default=None): > return next(iter(seq), default=default) > > > It could be optimized (implemented in C) if it makes it into the stdlib. > > > I don’t think it needs to be optimized. Most itertoolsy things that can be > built by composing existing functions (like most of the recipes) are fast > enough in Python; it’s the stuff that needs to loop and yield (like most of > the stuff actually in the module) that gets a major improvement in C. It’s > worth measuring rather than guessing, but my guess would be that the same > applies here. > > The only problem is that right now, the entire module is in C, so anything > that’s not optimized has to be a recipe and vice-versa. I’m pretty sure the > idea of splitting itertools into a Python module with a C accelerator (like > a lot of other modules in the stdlib) has come up before, but either > there’s never a good enough use case, or just nobody volunteers to do it. > And first might well be the candidate that’s worth it. > > Then again, maybe it is worth optimizing. Or maybe it’s fine to just list > it as a recipe (the recipes docs already link to more_itertools, which > already has it). > _______________________________________________ > 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/EEONODVROFGOL6AE3D7F772OHZYASRZN/ > Code of Conduct: http://python.org/psf/codeofconduct/ > -- --Guido (mobile)
_______________________________________________ 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/WYGECCEPYBYJF5ALJTMMVKT45FZIB2IG/ Code of Conduct: http://python.org/psf/codeofconduct/