max() allowed to take empty list

Many functions are happy to take empty lists:
But not max():
Allowing max to return None would make a lot of functional style programming easier, instead of explicitly having to check for empty lists or ignoring exceptions. None makes sense as a return value in many contexts. For example, hypothetical code like: if max(values) >= 90: return True # works even if values is [] thought not every case: a / max(values) # can't divide by None if values is []

On Mon, Apr 12, 2010 at 6:36 PM, Tom Pinckney <thomaspinckney3@gmail.com> wrote:
No, actually it *doesn't* work. It makes no sense to try and compare None to a number, and Python 3.x rightfully complains: Python 3.1.1 (r311:74480, Feb 1 2010, 23:08:45)
Errors should never pass silently unless explicitly silenced, so having None as a default fails on those grounds too. Adding a 'default value' parameter to max() to be returned when the iterable is empty would make slightly more sense. Cheers, Chris -- http://blog.rebertia.com

On Tue, Apr 13, 2010 at 2:52 AM, Chris Rebert <pyideas@rebertia.com> wrote:
Adding a 'default value' parameter to max() to be returned when the iterable is empty would make slightly more sense.
This has been proposed (and rejected) before: http://bugs.python.org/issue7153 Previous python-ideas thread: http://mail.python.org/pipermail/python-ideas/2009-April/004107.html The main problems (opportunities!) were: (1) the API for max and min is already complicated (single iterable argument versus multiple scalar arguments; 'key' parameter), and it's difficult to see how to clearly extend the API to take a default value (2) it wasn't clear whether it would make more sense to have a 'default' value---i.e., something that would be returned if the iterable is empty, and completely ignored otherwise, or a 'start' value---something that's added in to the mix of values in the iterable, so that the result is effectively the max of <iterable> + <[start]>. Mark

Tom Pinckney writes:
As Chris pointed out, this doesn't work at all in Python 3. But even in Python 2, one of "max([]) >= bound" and "min([]) >= bound" must fail to work correctly in terms of the mathematical limits for max and min. ">=" cannot know whether the "None" it sees was derived from "max([])", and should be interpreted as -infinity, or if it was derived from "min([])" and should be interpreted as +infinity. (And in fact it failed to error in Python 2 only because the comparison was done on the basis of the address of the object in memory, which is obviously pretty arbitrary, and in theory could even change from one invocation of Python to the next.) Since Python's built-in numbers don't support infinity, there's no way for those functions to return the appropriate mathematical objects, so they should error when given an empty sequence.

Stephen J. Turnbull wrote:
Small correction there: "not all of Python's built-in numbers". The bigger problem is that when using max() and min() the *type* of value you're dealing with will usually matter. Returning None is almost certainly wrong, but the functions otherwise have no idea what to return if an empty sequence is supplied, since they don't know what the program expected it to be a list *of* if it contains no values. In line with what Mark posted, the API extension that probably makes the most sense is to allow a bound to be specified in the call. For example: x = min(seq, upper_bound=0) x = min(seq, upper_bound=float('inf')) x = max(seq, lower_bound=0) x = max(seq, lower_bound=float('-inf')) where the stated bound is included in the values to be compared. This has some minor advantages over the alternatives, but would need some genuine real world use cases to justify complicating the core API. It also runs afoul of the language moratorium, and hence is off the table for the immediate future. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------

On Mon, Apr 12, 2010 at 6:36 PM, Tom Pinckney <thomaspinckney3@gmail.com> wrote:
No, actually it *doesn't* work. It makes no sense to try and compare None to a number, and Python 3.x rightfully complains: Python 3.1.1 (r311:74480, Feb 1 2010, 23:08:45)
Errors should never pass silently unless explicitly silenced, so having None as a default fails on those grounds too. Adding a 'default value' parameter to max() to be returned when the iterable is empty would make slightly more sense. Cheers, Chris -- http://blog.rebertia.com

On Tue, Apr 13, 2010 at 2:52 AM, Chris Rebert <pyideas@rebertia.com> wrote:
Adding a 'default value' parameter to max() to be returned when the iterable is empty would make slightly more sense.
This has been proposed (and rejected) before: http://bugs.python.org/issue7153 Previous python-ideas thread: http://mail.python.org/pipermail/python-ideas/2009-April/004107.html The main problems (opportunities!) were: (1) the API for max and min is already complicated (single iterable argument versus multiple scalar arguments; 'key' parameter), and it's difficult to see how to clearly extend the API to take a default value (2) it wasn't clear whether it would make more sense to have a 'default' value---i.e., something that would be returned if the iterable is empty, and completely ignored otherwise, or a 'start' value---something that's added in to the mix of values in the iterable, so that the result is effectively the max of <iterable> + <[start]>. Mark

Tom Pinckney writes:
As Chris pointed out, this doesn't work at all in Python 3. But even in Python 2, one of "max([]) >= bound" and "min([]) >= bound" must fail to work correctly in terms of the mathematical limits for max and min. ">=" cannot know whether the "None" it sees was derived from "max([])", and should be interpreted as -infinity, or if it was derived from "min([])" and should be interpreted as +infinity. (And in fact it failed to error in Python 2 only because the comparison was done on the basis of the address of the object in memory, which is obviously pretty arbitrary, and in theory could even change from one invocation of Python to the next.) Since Python's built-in numbers don't support infinity, there's no way for those functions to return the appropriate mathematical objects, so they should error when given an empty sequence.

Stephen J. Turnbull wrote:
Small correction there: "not all of Python's built-in numbers". The bigger problem is that when using max() and min() the *type* of value you're dealing with will usually matter. Returning None is almost certainly wrong, but the functions otherwise have no idea what to return if an empty sequence is supplied, since they don't know what the program expected it to be a list *of* if it contains no values. In line with what Mark posted, the API extension that probably makes the most sense is to allow a bound to be specified in the call. For example: x = min(seq, upper_bound=0) x = min(seq, upper_bound=float('inf')) x = max(seq, lower_bound=0) x = max(seq, lower_bound=float('-inf')) where the stated bound is included in the values to be compared. This has some minor advantages over the alternatives, but would need some genuine real world use cases to justify complicating the core API. It also runs afoul of the language moratorium, and hence is off the table for the immediate future. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
participants (5)
-
Chris Rebert
-
Mark Dickinson
-
Nick Coghlan
-
Stephen J. Turnbull
-
Tom Pinckney