
On Dec 14, 2019, at 21:52, David Mertz <mertz@gnosis.cx> wrote:
A pattern I've written a number of times is roughly:
lines = open(fname) header = next(lines) for line in lines: process (line, header)
That's not so artificial, I think. Of course, first() would also work here. But I'm not sure it's any particular advantage in this case.
I think first is actually worse here. If you might ever refactor this code to, say, take an arbitrary iterable as input rather than opening (and leaking) a file by name, using next means that forgetting to call iter somewhere is an easy to debug TypeError, but using first means it’s a subtle bug where the header is counted again as a normal row. But I also don’t think anyone will reach for first here. People who are already thinking of the file in terms of being an iterable are going to continue to use next. Everyone else is just going to call readline instead of either next or first. I think the advantages are in cases like the one Chris pointed out, where you have a dict view (or some other case where you know you have a non-iterator iterable but it isn’t, or at least might not be, a sequence), where first is helpful, for the reasons he described. For example, you’re at the REPL interactively working out how to process some web service: >>> p = requests.post(url) >>> r = p.json() >>> first(r.items()) ... here I see what I need to deal with Or maybe even that ends up bigger than you expected, but then you write: >>> things = _['things'] >>> things[0] ... still too big? ... >>> thing = things[0] >>> first(thing.items()) ... aha, now I get it Looking at my own REPL history and pile of throwaway scripts, dicts actually seem to make up a lot of my own uses of more_itertools.first.