[Python-ideas] fnmatch.filter_false

tritium-list at sdamon.com tritium-list at sdamon.com
Thu May 18 00:07:05 EDT 2017

> -----Original Message-----
> From: Python-ideas [mailto:python-ideas-bounces+tritium-
> list=sdamon.com at python.org] On Behalf Of Steven D'Aprano
> Sent: Wednesday, May 17, 2017 9:01 PM
> To: python-ideas at python.org
> Subject: Re: [Python-ideas] fnmatch.filter_false
> On Wed, May 17, 2017 at 12:14:05PM -0400, Alex Walters wrote:
> > Fnmath.filter works great.  To remind people what it does, it takes an
> > iterable of strings and a pattern and returns a list of the strings that
> > match the pattern.  And that is wonderful
> >
> > However, I often need to filter *out* the items that match the pattern
> > ignore them).  In every project that I need this I end up copying the
> > function out of the fnmatch library and adding 'not' to the test clause.
> At the cost of a slight inefficiency, you could use the pure Python
> equivalent given in the docs:
> https://docs.python.org/3/library/fnmatch.html#fnmatch.filter
> fnmatch.filter(names, pattern)
>     Return the subset of the list of names that match pattern. It is
>     the same as [n for n in names if fnmatch(n, pattern)], but implemented
>     more efficiently.
> So your filter_false is:
>     [n for n in names if not fnmatch(n, pattern)]
> which avoids the need for the copy-and-paste anti-pattern.

I ran a test on the same dataset using listcomps.  The modified version of
filter is still 22.<some noise>, the unmodified version is still 19.<some
noise>.  However the listcomp method is 41.<some noise>.  That performance
is important, at least to me.  Before you ask, yes, I have profiled my code,
and filtering is a bottleneck.

> Otherwise, I would support:
> - filter_false
> - or a glob symbol to reverse the sense of the test, e.g. ~ or !
>   as the first character;
> but I dislike functions that take boolean arguments to change their
> behaviour. It's not a 100% hard and fast rule, but in general I prefer
> to avoid functions that take a constant bool argument:
> # rather than this:
> function(important_args, True)
> function(important_args, False)
> # use this:
> function(important_args)
> function_false(important_args)
> (although there may be exceptions).

That is a fair enough argument.  In moderate defense of the code I posted
earlier, I did make the inversion variable keyword only.

> --
> Steve
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/

More information about the Python-ideas mailing list