max(), sum(), next()

David C. Ullrich dullrich at sprynet.com
Thu Sep 4 12:17:37 EDT 2008


In article 
<24061e7d-935a-442f-8d50-b8619d5581d3 at 34g2000hsh.googlegroups.com>,
 bearophileHUGS at lycos.com wrote:

> Empty Python lists [] don't know the type of the items it will
> contain, so this sounds strange:
> 
> >>> sum([])
> 0
> 
> Because that [] may be an empty sequence of someobject:
> 
> >>> sum(s for s in ["a", "b"] if len(s) > 2)
> 0
> 
> In a statically typed language in that situation you may answer the
> initializer value of the type of the items of the list, as I do in the
> sum() in D.
> 
> This sounds like a more correct/clean thing to do:
> 
> >>> max([])
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> ValueError: max() arg is an empty sequence
> 
> So it may be better to make the sum([]) too raise a ValueError,

I don't see why you feel the two should act the same.
At least in mathematics, the sum of the elements of
the empty set _is_ 0, while the maximum element of the
empty set is undefined. 

And both for good reason:

(i) If A and B are disjoint sets we certainly want to
have sum(A union B) = sum(A) + sum(B). This requires
sum(empty set) = 0.

(ii) If A is a subset of B then we should have
max(A) <= max(B). This requires that max(empty set)
be something that's smaller than everything else.
So we give up on that.

> in
> Python 3/3.1 (if this isn't already true). On the other hand often
> enough I have code like this:
> 
> >>> max(fun(x) for x in iterable if predicate(x))
> 
> This may raise the ValueError both if iterable is empty of if the
> predicate on its items is always false, so instead of catching
> exceptions, that I try to avoid, I usually end with a normal loop,
> that's readable and fast:
> 
> max_value = smallvalue
> for x in iterable:
>     if predicate(x):
>         max_value = max(max_value, fun(x))
> 
> Where running speed matters, I may even replace that max(max_value,
> fun(x)) with a more normal if/else.
> 
> A possible alternative is to add a default to max(), like the next()
> built-in of Python 2.6:
> 
> >>> max((fun(x) for x in iterable if predicate(x)), default=smallvalue)
> 
> This returns smallvalue if there are no items to compute the max of.
> 
> Bye,
> bearophile

-- 
David C. Ullrich



More information about the Python-list mailing list