[Python-ideas] Allow filter(items)

Andrew Barnert abarnert at yahoo.com
Thu Aug 8 00:08:31 CEST 2013


On Aug 7, 2013, at 14:15, Terry Reedy <tjreedy at udel.edu> wrote:

> 
> 
> On 8/7/2013 4:54 PM, Andrew Barnert wrote:
>> On Aug 7, 2013, at 10:31, Terry Reedy <tjreedy at udel.edu> wrote:
>> 
>>> On 8/7/2013 6:01 AM, Alexander Belopolsky wrote:
>>> 
>>>> From Guido's time machine comes a pronouncement:
>>> <http://bugs.python.org/issue2186#msg63026>.
>>> 
>>> As Raymond points out in a later message, it is standard in Python for None passed to a function to mean 'no argument, do something that does not require an value for this parameter'. It does not mean 'use a value of None for this parameter and do with None whatever would be done with any other value'.
>>> 
>>> Usually, only trailing parameters are allowed to be given None and then it is given in the definition as a default.
>>>  def f(a, b=None, c=None): pass
>>> can be called f(x), f(x, y), f(x, y, z), and f(x, None, z) or f(x, c=z). Because of the last option, there is never a need for the user to explicitly pass None.
>>> 
>>> What is unusual about filter is not the use of None to mean 'no argument, behave differently', but the need for it to be written explicitly by the caller to get the null behavior.
>> 
>> There are other functions like that. For example, to set a max split, but still get the default behavior of splitting on any whitespace instead of a specific character, you have to write s.split(None, 2).
> 
> As with "f(x, None, z) or f(x, c=z)', that, *or*
> >>> 'a b c d'.split(maxsplit=2)
> ['a', 'b', 'c d']
> 
> .split is similar to filter in using None to mean 'do something different'. In this case, it is 'do not split an any one string but on any whitespace span. I believe this is equivalent to re.split('\s+', ...), but without importing the re module and invoking it full overhead.
> 
>> I'm not suggesting that it's an ideal design, just that it's not uniquely special to filter.
> 
> If one tries the 'or' option with filter
> 
> filter(iterable=[0,1,2])
> Traceback (most recent call last):
>  File "<pyshell#3>", line 1, in <module>
>    filter(iterable=[0,1,2])
> TypeError: filter() does not take keyword arguments

That's just an implementation detail. The split method didn't always take keyword args either; now it does. We could easily define filter as (in pseudo-Python instead of C):

    def filter(predicate=None, iterable=None):
        if iterable is None:
            raise TypeError("can't filter None")
        ...

Then you could call it as filter(None, bariter) or filter(iterable=bariter), just like split.

It's still clumsier that having optional, often-skipped arguments last, but my point is that doesn't make it unique.

> 
> and even if it did, one would get a TypeError for passing only 1 arg when 2 are needed.
> 
> --
> Terry Jan Reedy


More information about the Python-ideas mailing list