[Python-ideas] 'default' keyword argument for max(), min()

Raymond Hettinger python at rcn.com
Fri Apr 17 01:07:10 CEST 2009

> Yes, I often use min/max with gen. expressions: Compare:
>     if min(f(x) for x in iterable if x>0) > 0:

Do you mean:
      if min((f(x) for x in iterable if x>0), default=0) > 0: ...

I don't find that to be a clear expression of what you're trying to do.
Too much logic forced into a one-liner (also note that the inner parens
are required).

> with
>   _values = [f(x) for x in iterable if x>0]
>   if _values and min(_values) > 0:

or with:
   if all(f(x)>0 for x in iterable if x>0):             ...

I think you're focusing on just one solution, one that involves piling-up
too many extensions in one function that should be dirt simple.  There
are many other approaches:  try/except, wrap the input in a default
itertool, use all(), use next(it, default) to test the first value, etc.

>> The discussion has indeed sidetracked with handling the special cases,
>> signature definition and whatnot, but I believe meeting the conditions
>> you outlined above is not as rare as their number implies. 

This may be a symptom of a particular programming style.
I've found zero useful examples in scans of the standard library,
in my own personal code base, or third-party extensions that I use regularly.

>> I hope the
>> rest of the thread focuses on this motivating case so that this
>> proposal is not rejected due to excessive bikeshedding.

A discussion of use cases is always helpful, but the rest of
the discussion wasn't bikeshedding.  It revealed that the
default-argument doesn't make sense with non-iterable positional
arguments and that some were confusing it with an initial-argument.
No one yet has produced a clean, pure-python version that only 
affects a single iterable argument (ignoring positional cases where
a default doesn't make sense) and that doesn't wrap the existing 
min/max code (it is important to look at the fully spelled-out 
pure python code to see that the overall design, taking all features 
into account, isn't clean).

Also, I did a couple quick checks on other languages to see
any use a default for empty min() but had no luck.  Do you
know of any languages where a min() with default is a 
proven best practice?

> As an aside, it would be nice If min/max start raising a more narrow
> ValueError subtype, say EmptyIterableError, so that hacks such as
> checking the exception message are not necessary.

I would support that proposal if it would end this effort to
complexify min/max.  


FWIW, here's an itertool recipe that you may find useful.

def default(iterable, default=None):
    '''Yield elements of the iterable or if it is empty, yield the default.

    default([1,2,3], default=0) --> 1 2 3
    default([], default=0)      --> 0        

    it = iter(iterable)
    return chain([next(it, default)], it)

More information about the Python-ideas mailing list