|  | max(), sum(), next() |  | |
| | | Guest |  |
| Posted: Wed Sep 03, 2008 12:48 pm Post subject: max(), sum(), next() |  |
| |  | |
Empty Python lists [] don't know the type of the items it will contain, so this sounds strange:
Because that [] may be an empty sequence of someobject:
| Quote: | 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:
| Quote: | 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, in Python 3/3.1 (if this isn't already true). On the other hand often enough I have code like this:
| Quote: | 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:
| Quote: | 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 |
| |
| | | Sion Arrowsmith |  |
| Posted: Wed Sep 03, 2008 2:06 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
<bearophileHUGS@lycos.com> wrote:
| Quote: | Empty Python lists [] don't know the type of the items it will contain, so this sounds strange:
sum([]) 0
help(sum) sum(...) |
sum(sequence, start=0) -> value
| Quote: | sum(range(x) for x in range(5)) Traceback (most recent call last): |
File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'list'
| Quote: | sum((range(x) for x in range(5)), []) [0, 0, 1, 0, 1, 2, 0, 1, 2, 3] |
.... so the list might not know what type it contains, but sum does. And if you don't tell it, it makes a sensible guess. And it *is* a case where refusing the temptation to guess is the wrong thing: how many times would you use sum to do anything other than sum numeric values? And how tedious would it be to have to write sum(..., 0) for every other case? Particularly bearing in mind:
| Quote: | sum(["a", "b"], "") Traceback (most recent call last): |
File "<stdin>", line 1, in <module> TypeError: sum() can't sum strings [use ''.join(seq) instead]
-- \S -- siona@chiark.greenend.org.uk -- LINK "Frankly I have no feelings towards penguins one way or the other" -- Arthur C. Clarke her nu becomež se bera eadward ofdun hlęddre heafdes bęce bump bump bump |
| |
| | | Laszlo Nagy |  |
| Posted: Wed Sep 03, 2008 5:18 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
bearophileHUGS@lycos.com wrote:
| Quote: | 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:
|
You are right in that sum could be used to sum arbitrary objects. However, in 99.99% of the cases, you will be summing numerical values. When adding real numbers, the neutral element is zero. ( X + 0 = X) It is very logical to return zero for empty sequences.
Same way, if we would have a prod() function, it should return one for empty sequences because X*1 = X. The neutral element for this operation is one.
Of course this is not good for summing other types of objects. But how clumsy would it be to use
sum( L +[0] )
or
if L: value = sum(L) else: value = 0
instead of sum(L).
Once again, this is what sum() is used for in most cases, so this behavior is the "expected" one.
Another argument to convince you: the sum() function in SQL for empty row sets returns zero in most relational databases.
But of course it could have been implemented in a different way... I believe that there have been excessive discussions about this decision, and the current implementation is very good, if not the best.
Best,
Laszlo |
| |
| | | MRAB |  |
| Posted: Wed Sep 03, 2008 10:40 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
On Sep 3, 8:18 pm, Laszlo Nagy <gand...@shopzeus.com> wrote:
| Quote: | bearophileH...@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:
You are right in that sum could be used to sum arbitrary objects. However, in 99.99% of the cases, you will be summing numerical values. When adding real numbers, the neutral element is zero. ( X + 0 = X) It is very logical to return zero for empty sequences.
Same way, if we would have a prod() function, it should return one for empty sequences because X*1 = X. The neutral element for this operation is one.
Of course this is not good for summing other types of objects. But how clumsy would it be to use
sum( L +[0] )
or
if L: value = sum(L) else: value = 0
instead of sum(L).
Once again, this is what sum() is used for in most cases, so this behavior is the "expected" one.
Another argument to convince you: the sum() function in SQL for empty row sets returns zero in most relational databases.
But of course it could have been implemented in a different way... I believe that there have been excessive discussions about this decision, and the current implementation is very good, if not the best.
An alternative would be for the start value to default to None, which |
would mean no start value. At the moment it starts with the start value and then 'adds' the items in the sequence to it, but it could start with the first item and then 'add' the following items to it. So:
sum([1, 2, 3]) => 6 sum(["a", "b", "c"]) => "abc"
For backward compatibility, if the sequence is empty and the start value is None then return 0. |
| |
| | | Guest |  |
| Posted: Wed Sep 03, 2008 11:00 pm Post subject: Re: max(), sum(), next() |  |
Laszlo Nagy:
| Quote: | I believe that there have been excessive discussions about this decision, and the current implementation is very good, if not the best.
|
I see. But note that my post is mostly about the max()/min() functions :-)
Bye, bearophile |
| |
| | | Mensanator |  |
| Posted: Wed Sep 03, 2008 11:20 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
On Sep 3, 2:18 pm, Laszlo Nagy <gand...@shopzeus.com> wrote:
| Quote: | bearophileH...@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:
You are right in that sum could be used to sum arbitrary objects. However, in 99.99% of the cases, you will be summing numerical values. When adding real numbers, the neutral element is zero. ( X + 0 = X) It is very logical to return zero for empty sequences.
|
No it isn't. Nothing is not 0, check with MS-Access, for instance:
Null + 1 returns Null. Any arithmetic expression involving a Null evaluates to Null. Adding something to an unknown returns an unknown, as it should.
It is a logical fallacy to equate unknown with 0.
For example, the water table elevation in ft above Mean Sea Level is WTE = TopOfCasing - DepthToWater.
TopOfCasing is usually known and constant (until resurveyed). But DepthToWater may or may not exist for a given event (well may be covered with fire ants, for example).
Now, if you equate Null with 0, then the WTE calculation says the water table elevation is flush with the top of the well, falsely implying that the site is underwater.
And, since this particular site is on the Mississippi River, it sometimes IS underwater, but this is NEVER determined by water table elevations, which, due to the CORRECT treatment of Nulls by Access, never returns FALSE calculations.
is a bug, just as it's a bug in Excel to evaluate blank cells as 0. It should return None or throw an exception like sum([None,1]) does.
| Quote: | Same way, if we would have a prod() function, it should return one for empty sequences because X*1 = X. The neutral element for this operation is one.
Of course this is not good for summing other types of objects. But how clumsy would it be to use
sum( L +[0] )
or
if L: value = sum(L) else: value = 0
instead of sum(L).
Once again, this is what sum() is used for in most cases, so this behavior is the "expected" one.
Another argument to convince you: the sum() function in SQL for empty row sets returns zero in most relational databases.
But of course it could have been implemented in a different way... I believe that there have been excessive discussions about this decision, and the current implementation is very good, if not the best.
Best,
Laszlo |
|
| |
| | | Steven D'Aprano |  |
| Posted: Wed Sep 03, 2008 11:30 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
On Wed, 03 Sep 2008 16:20:39 -0700, Mensanator wrote:
| Quote: | sum([]) 0
is a bug, just as it's a bug in Excel to evaluate blank cells as 0. It should return None or throw an exception like sum([None,1]) does.
|
You're wrong, because 99.9% of the time when users leave a blank cell in Excel, they want it to be treated as zero. Spreadsheet sum() is not the same as mathematician's sum, which doesn't have a concept of "blank cells". (But if it did, it would treat them as zero, since that's the only useful thing and mathematicians are just as much pragmatists as spreadsheet users.) The Excel code does the right thing, and your "pure" solution would do the unwanted and unexpected thing and is therefore buggy.
Bugs are defined by "does the code do what the user wants it to do?", not "is it mathematically pure?". The current behaviour of sum([]) does the right thing for the 99% of the time when users expect an integer. And the rest of the time, they have to specify a starting value for the sum anyway, and so sum([], initial_value) does the right thing *always*.
The only time it does the wrong thing[1] is when you forget to pass an initial value but expect a non-numeric result. And that's the programmer's error, not a function bug.
[1] I believe it also does the wrong thing by refusing to sum strings, but that's another story.
-- Steven |
| |
| | | castironpi |  |
| Posted: Wed Sep 03, 2008 11:34 pm Post subject: Re: max(), sum(), next() |  |
| |  | |
On Sep 3, 7:48 am, bearophileH...@lycos.com wrote:
| Quote: | 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, 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
|
Two thoughts: 1/ 'Reduce' has a 'default' argument-- they call it 'initial'.
| Quote: | reduce( max, [ 0, 1, 2, 3 ] ) 3 reduce( max, [ 0, 1, 2, 'a' ] ) 'a' reduce( max, [ 0, 1, 2, 'a', 'b' ] ) 'b' |
2/ Introduce a 'max' class object that takes a default type or default argument. Query the default for an 'additive' identity, or query for a 'comparitive' identity, comparisons to which always return true; or call the constructor with no arguments to construct one. |
| |
| | | Luis Zarrabeitia |  |
| Posted: Thu Sep 04, 2008 1:40 am Post subject: Re: max(), sum(), next() |  |
| |  | |
Quoting Laszlo Nagy <gandalf@shopzeus.com>:
| Quote: | bearophileHUGS@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:
You are right in that sum could be used to sum arbitrary objects. However, in 99.99% of the cases, you will be summing numerical values. When adding real numbers, the neutral element is zero. ( X + 0 = X) It is very logical to return zero for empty sequences.
|
Even better:
help(sum) shows
==sum(...) sum(sequence, start=0) -> value Returns the sum of a sequence of numbers (NOT strings) plus the value of parameter 'start'. When the sequence is empty, returns start. == so the fact that sum([]) returns zero is just because the start value is zero... sum([],object()) would return an object().
BTW, the original code:
| Quote: | sum(s for s in ["a", "b"] if len(s) > 2)
|
wouldn't work anyway... it seems that sum doesn't like to sum strings:
<type 'exceptions.TypeError'>: sum() can't sum strings [use ''.join(seq) instead]
Cheers,
-- Luis Zarrabeitia Facultad de Matemįtica y Computación, UH LINK |
| |
| | | Fredrik Lundh |  |
| Posted: Thu Sep 04, 2008 4:24 am Post subject: Re: max(), sum(), next() |  |
Mensanator wrote:
| Quote: | No it isn't. Nothing is not 0, check with MS-Access, for instance:
Null + 1 returns Null. Any arithmetic expression involving a Null evaluates to Null. Adding something to an unknown returns an unknown, as it should.
It is a logical fallacy to equate unknown with 0.
|
LINK
"In mathematics, the empty sum, or nullary sum, is the result of adding no numbers, in summation for example. Its numerical value is zero."
</F> |
| |
| Page 1 of 2 .:. Goto page 1, 2 Next | |
|
|