Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
4d6018fe
Commit
4d6018fe
authored
Jun 24, 2013
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue 18111: Add a default argument to min() and max()
parent
d7a034bd
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
78 additions
and
28 deletions
+78
-28
Doc/library/functions.rst
Doc/library/functions.rst
+20
-14
Lib/test/test_builtin.py
Lib/test/test_builtin.py
+28
-0
Misc/NEWS
Misc/NEWS
+4
-0
Python/bltinmodule.c
Python/bltinmodule.c
+26
-14
No files found.
Doc/library/functions.rst
View file @
4d6018fe
...
@@ -753,19 +753,22 @@ are always available. They are listed here in alphabetical order.
...
@@ -753,19 +753,22 @@ are always available. They are listed here in alphabetical order.
already arranged into argument tuples, see :func:`itertools.starmap`\.
already arranged into argument tuples, see :func:`itertools.starmap`\.
.. function:: max(iterable, *[, key])
.. function:: max(iterable, *[,
default,
key])
max(arg1, arg2, *args[, key])
max(arg1, arg2, *args[, key])
Return the largest item in an iterable or the largest of two or more
Return the largest item in an iterable or the largest of two or more
arguments.
arguments.
If one positional argument is provided,
*iterable* must be a non-empty
If one positional argument is provided,
it should be an :term:`iterable`.
iterable (such as a non-empty string, tuple or list). The largest item
The largest item in the iterable is returned. If two or more positional
in the iterable is returned. If two or more positional arguments are
arguments are provided, the smallest of the positional arguments is
provided, the largest of the positional arguments is
returned.
returned.
The optional keyword-only *key* argument specifies a one-argument ordering
There are two optional keyword-only arguments. The *key* argument specifies
function like that used for :meth:`list.sort`.
a one-argument ordering function like that used for :meth:`list.sort`. The
*default* argument specifies an object to return if the provided iterable is
empty. If the iterable is empty and *default* is not provided, a
:exc:`ValueError` is raised.
If multiple items are maximal, the function returns the first one
If multiple items are maximal, the function returns the first one
encountered. This is consistent with other sort-stability preserving tools
encountered. This is consistent with other sort-stability preserving tools
...
@@ -781,19 +784,22 @@ are always available. They are listed here in alphabetical order.
...
@@ -781,19 +784,22 @@ are always available. They are listed here in alphabetical order.
:ref:`typememoryview` for more information.
:ref:`typememoryview` for more information.
.. function:: min(iterable, *[, key])
.. function:: min(iterable, *[,
default,
key])
min(arg1, arg2, *args[, key])
min(arg1, arg2, *args[, key])
Return the smallest item in an iterable or the smallest of two or more
Return the smallest item in an iterable or the smallest of two or more
arguments.
arguments.
If one positional argument is provided,
*iterable* must be a non-empty
If one positional argument is provided,
it should be an :term:`iterable`.
iterable (such as a non-empty string, tuple or list). The smallest item
The smallest item in the iterable is returned. If two or more positional
in the iterable is returned. If two or more positional arguments are
arguments are provided, the smallest of the positional arguments is
provided, the smallest of the positional arguments is
returned.
returned.
The optional keyword-only *key* argument specifies a one-argument ordering
There are two optional keyword-only arguments. The *key* argument specifies
function like that used for :meth:`list.sort`.
a one-argument ordering function like that used for :meth:`list.sort`. The
*default* argument specifies an object to return if the provided iterable is
empty. If the iterable is empty and *default* is not provided, a
:exc:`ValueError` is raised.
If multiple items are minimal, the function returns the first one
If multiple items are minimal, the function returns the first one
encountered. This is consistent with other sort-stability preserving tools
encountered. This is consistent with other sort-stability preserving tools
...
...
Lib/test/test_builtin.py
View file @
4d6018fe
...
@@ -847,8 +847,19 @@ class BuiltinTest(unittest.TestCase):
...
@@ -847,8 +847,19 @@ class BuiltinTest(unittest.TestCase):
self
.
assertEqual
(
max
(
1
,
2.0
,
3
),
3
)
self
.
assertEqual
(
max
(
1
,
2.0
,
3
),
3
)
self
.
assertEqual
(
max
(
1.0
,
2
,
3
),
3
)
self
.
assertEqual
(
max
(
1.0
,
2
,
3
),
3
)
self
.
assertRaises
(
TypeError
,
max
)
self
.
assertRaises
(
TypeError
,
max
,
42
)
self
.
assertRaises
(
ValueError
,
max
,
())
class
BadSeq
:
def
__getitem__
(
self
,
index
):
raise
ValueError
self
.
assertRaises
(
ValueError
,
max
,
BadSeq
())
for
stmt
in
(
for
stmt
in
(
"max(key=int)"
,
# no args
"max(key=int)"
,
# no args
"max(default=None)"
,
"max(1, 2, default=None)"
,
# require container for default
"max(default=None, key=int)"
,
"max(1, key=int)"
,
# single arg not iterable
"max(1, key=int)"
,
# single arg not iterable
"max(1, 2, keystone=int)"
,
# wrong keyword
"max(1, 2, keystone=int)"
,
# wrong keyword
"max(1, 2, key=int, abc=int)"
,
# two many keywords
"max(1, 2, key=int, abc=int)"
,
# two many keywords
...
@@ -865,6 +876,13 @@ class BuiltinTest(unittest.TestCase):
...
@@ -865,6 +876,13 @@ class BuiltinTest(unittest.TestCase):
self
.
assertEqual
(
max
((
1
,
2
),
key
=
neg
),
1
)
# two elem iterable
self
.
assertEqual
(
max
((
1
,
2
),
key
=
neg
),
1
)
# two elem iterable
self
.
assertEqual
(
max
(
1
,
2
,
key
=
neg
),
1
)
# two elems
self
.
assertEqual
(
max
(
1
,
2
,
key
=
neg
),
1
)
# two elems
self
.
assertEqual
(
max
((),
default
=
None
),
None
)
# zero elem iterable
self
.
assertEqual
(
max
((
1
,),
default
=
None
),
1
)
# one elem iterable
self
.
assertEqual
(
max
((
1
,
2
),
default
=
None
),
2
)
# two elem iterable
self
.
assertEqual
(
max
((),
default
=
1
,
key
=
neg
),
1
)
self
.
assertEqual
(
max
((
1
,
2
),
default
=
3
,
key
=
neg
),
1
)
data
=
[
random
.
randrange
(
200
)
for
i
in
range
(
100
)]
data
=
[
random
.
randrange
(
200
)
for
i
in
range
(
100
)]
keys
=
dict
((
elem
,
random
.
randrange
(
50
))
for
elem
in
data
)
keys
=
dict
((
elem
,
random
.
randrange
(
50
))
for
elem
in
data
)
f
=
keys
.
__getitem__
f
=
keys
.
__getitem__
...
@@ -891,6 +909,9 @@ class BuiltinTest(unittest.TestCase):
...
@@ -891,6 +909,9 @@ class BuiltinTest(unittest.TestCase):
for
stmt
in
(
for
stmt
in
(
"min(key=int)"
,
# no args
"min(key=int)"
,
# no args
"min(default=None)"
,
"min(1, 2, default=None)"
,
# require container for default
"min(default=None, key=int)"
,
"min(1, key=int)"
,
# single arg not iterable
"min(1, key=int)"
,
# single arg not iterable
"min(1, 2, keystone=int)"
,
# wrong keyword
"min(1, 2, keystone=int)"
,
# wrong keyword
"min(1, 2, key=int, abc=int)"
,
# two many keywords
"min(1, 2, key=int, abc=int)"
,
# two many keywords
...
@@ -907,6 +928,13 @@ class BuiltinTest(unittest.TestCase):
...
@@ -907,6 +928,13 @@ class BuiltinTest(unittest.TestCase):
self
.
assertEqual
(
min
((
1
,
2
),
key
=
neg
),
2
)
# two elem iterable
self
.
assertEqual
(
min
((
1
,
2
),
key
=
neg
),
2
)
# two elem iterable
self
.
assertEqual
(
min
(
1
,
2
,
key
=
neg
),
2
)
# two elems
self
.
assertEqual
(
min
(
1
,
2
,
key
=
neg
),
2
)
# two elems
self
.
assertEqual
(
min
((),
default
=
None
),
None
)
# zero elem iterable
self
.
assertEqual
(
min
((
1
,),
default
=
None
),
1
)
# one elem iterable
self
.
assertEqual
(
min
((
1
,
2
),
default
=
None
),
1
)
# two elem iterable
self
.
assertEqual
(
min
((),
default
=
1
,
key
=
neg
),
1
)
self
.
assertEqual
(
min
((
1
,
2
),
default
=
1
,
key
=
neg
),
2
)
data
=
[
random
.
randrange
(
200
)
for
i
in
range
(
100
)]
data
=
[
random
.
randrange
(
200
)
for
i
in
range
(
100
)]
keys
=
dict
((
elem
,
random
.
randrange
(
50
))
for
elem
in
data
)
keys
=
dict
((
elem
,
random
.
randrange
(
50
))
for
elem
in
data
)
f
=
keys
.
__getitem__
f
=
keys
.
__getitem__
...
...
Misc/NEWS
View file @
4d6018fe
...
@@ -13,6 +13,10 @@ Core and Builtins
...
@@ -13,6 +13,10 @@ Core and Builtins
- Issue #18184: PyUnicode_FromFormat() and PyUnicode_FromFormatV() now raise
- Issue #18184: PyUnicode_FromFormat() and PyUnicode_FromFormatV() now raise
OverflowError when an argument of %c format is out of range.
OverflowError when an argument of %c format is out of range.
- Issue #18111: The min() and max() functions now support a default argument
to be returned instead of raising a ValueError on an empty sequence.
(Contributed by Julian Berman.)
- Issue #18137: Detect integer overflow on precision in float.__format__()
- Issue #18137: Detect integer overflow on precision in float.__format__()
and complex.__format__().
and complex.__format__().
...
...
Python/bltinmodule.c
View file @
4d6018fe
...
@@ -1329,26 +1329,35 @@ static PyObject *
...
@@ -1329,26 +1329,35 @@ static PyObject *
min_max
(
PyObject
*
args
,
PyObject
*
kwds
,
int
op
)
min_max
(
PyObject
*
args
,
PyObject
*
kwds
,
int
op
)
{
{
PyObject
*
v
,
*
it
,
*
item
,
*
val
,
*
maxitem
,
*
maxval
,
*
keyfunc
=
NULL
;
PyObject
*
v
,
*
it
,
*
item
,
*
val
,
*
maxitem
,
*
maxval
,
*
keyfunc
=
NULL
;
PyObject
*
emptytuple
,
*
defaultval
=
NULL
;
static
char
*
kwlist
[]
=
{
"key"
,
"default"
,
NULL
};
const
char
*
name
=
op
==
Py_LT
?
"min"
:
"max"
;
const
char
*
name
=
op
==
Py_LT
?
"min"
:
"max"
;
const
int
positional
=
PyTuple_Size
(
args
)
>
1
;
int
ret
;
if
(
PyTuple_Size
(
args
)
>
1
)
if
(
positional
)
v
=
args
;
v
=
args
;
else
if
(
!
PyArg_UnpackTuple
(
args
,
(
char
*
)
name
,
1
,
1
,
&
v
))
else
if
(
!
PyArg_UnpackTuple
(
args
,
(
char
*
)
name
,
1
,
1
,
&
v
))
return
NULL
;
return
NULL
;
if
(
kwds
!=
NULL
&&
PyDict_Check
(
kwds
)
&&
PyDict_Size
(
kwds
))
{
emptytuple
=
PyTuple_New
(
0
);
keyfunc
=
PyDict_GetItemString
(
kwds
,
"key"
);
if
(
emptytuple
==
NULL
)
if
(
PyDict_Size
(
kwds
)
!=
1
||
keyfunc
==
NULL
)
{
return
NULL
;
ret
=
PyArg_ParseTupleAndKeywords
(
emptytuple
,
kwds
,
"|$OO"
,
kwlist
,
&
keyfunc
,
&
defaultval
);
Py_DECREF
(
emptytuple
);
if
(
!
ret
)
return
NULL
;
if
(
positional
&&
defaultval
!=
NULL
)
{
PyErr_Format
(
PyExc_TypeError
,
PyErr_Format
(
PyExc_TypeError
,
"%s() got an unexpected keyword argument"
,
name
);
"Cannot specify a default for %s() with multiple "
"positional arguments"
,
name
);
return
NULL
;
return
NULL
;
}
}
Py_INCREF
(
keyfunc
);
}
it
=
PyObject_GetIter
(
v
);
it
=
PyObject_GetIter
(
v
);
if
(
it
==
NULL
)
{
if
(
it
==
NULL
)
{
Py_XDECREF
(
keyfunc
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1392,14 +1401,18 @@ min_max(PyObject *args, PyObject *kwds, int op)
...
@@ -1392,14 +1401,18 @@ min_max(PyObject *args, PyObject *kwds, int op)
if
(
PyErr_Occurred
())
if
(
PyErr_Occurred
())
goto
Fail_it
;
goto
Fail_it
;
if
(
maxval
==
NULL
)
{
if
(
maxval
==
NULL
)
{
assert
(
maxitem
==
NULL
);
if
(
defaultval
!=
NULL
)
{
Py_INCREF
(
defaultval
);
maxitem
=
defaultval
;
}
else
{
PyErr_Format
(
PyExc_ValueError
,
PyErr_Format
(
PyExc_ValueError
,
"%s() arg is an empty sequence"
,
name
);
"%s() arg is an empty sequence"
,
name
);
assert
(
maxitem
==
NULL
);
}
}
}
else
else
Py_DECREF
(
maxval
);
Py_DECREF
(
maxval
);
Py_DECREF
(
it
);
Py_DECREF
(
it
);
Py_XDECREF
(
keyfunc
);
return
maxitem
;
return
maxitem
;
Fail_it_item_and_val:
Fail_it_item_and_val:
...
@@ -1410,7 +1423,6 @@ Fail_it:
...
@@ -1410,7 +1423,6 @@ Fail_it:
Py_XDECREF
(
maxval
);
Py_XDECREF
(
maxval
);
Py_XDECREF
(
maxitem
);
Py_XDECREF
(
maxitem
);
Py_DECREF
(
it
);
Py_DECREF
(
it
);
Py_XDECREF
(
keyfunc
);
return
NULL
;
return
NULL
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment