bpo-34149: Behavior of the min/max with key=None (GH-8328)
Improve consistency with the signature for sorted(), heapq.nsmallest(), heapq.nlargest(), and itertools.groupby().
This commit is contained in:
parent
bde782bb59
commit
e22072fb11
|
@ -869,6 +869,9 @@ are always available. They are listed here in alphabetical order.
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
The *default* keyword-only argument.
|
The *default* keyword-only argument.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8
|
||||||
|
The *key* can be ``None``.
|
||||||
|
|
||||||
|
|
||||||
.. _func-memoryview:
|
.. _func-memoryview:
|
||||||
.. function:: memoryview(obj)
|
.. function:: memoryview(obj)
|
||||||
|
@ -903,6 +906,9 @@ are always available. They are listed here in alphabetical order.
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
The *default* keyword-only argument.
|
The *default* keyword-only argument.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.8
|
||||||
|
The *key* can be ``None``.
|
||||||
|
|
||||||
|
|
||||||
.. function:: next(iterator[, default])
|
.. function:: next(iterator[, default])
|
||||||
|
|
||||||
|
|
10
Lib/heapq.py
10
Lib/heapq.py
|
@ -468,10 +468,7 @@ def nsmallest(n, iterable, key=None):
|
||||||
if n == 1:
|
if n == 1:
|
||||||
it = iter(iterable)
|
it = iter(iterable)
|
||||||
sentinel = object()
|
sentinel = object()
|
||||||
if key is None:
|
result = min(it, default=sentinel, key=key)
|
||||||
result = min(it, default=sentinel)
|
|
||||||
else:
|
|
||||||
result = min(it, default=sentinel, key=key)
|
|
||||||
return [] if result is sentinel else [result]
|
return [] if result is sentinel else [result]
|
||||||
|
|
||||||
# When n>=size, it's faster to use sorted()
|
# When n>=size, it's faster to use sorted()
|
||||||
|
@ -531,10 +528,7 @@ def nlargest(n, iterable, key=None):
|
||||||
if n == 1:
|
if n == 1:
|
||||||
it = iter(iterable)
|
it = iter(iterable)
|
||||||
sentinel = object()
|
sentinel = object()
|
||||||
if key is None:
|
result = max(it, default=sentinel, key=key)
|
||||||
result = max(it, default=sentinel)
|
|
||||||
else:
|
|
||||||
result = max(it, default=sentinel, key=key)
|
|
||||||
return [] if result is sentinel else [result]
|
return [] if result is sentinel else [result]
|
||||||
|
|
||||||
# When n>=size, it's faster to use sorted()
|
# When n>=size, it's faster to use sorted()
|
||||||
|
|
|
@ -905,6 +905,8 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(max((), default=1, key=neg), 1)
|
self.assertEqual(max((), default=1, key=neg), 1)
|
||||||
self.assertEqual(max((1, 2), default=3, key=neg), 1)
|
self.assertEqual(max((1, 2), default=3, key=neg), 1)
|
||||||
|
|
||||||
|
self.assertEqual(max((1, 2), key=None), 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__
|
||||||
|
@ -957,6 +959,8 @@ class BuiltinTest(unittest.TestCase):
|
||||||
self.assertEqual(min((), default=1, key=neg), 1)
|
self.assertEqual(min((), default=1, key=neg), 1)
|
||||||
self.assertEqual(min((1, 2), default=1, key=neg), 2)
|
self.assertEqual(min((1, 2), default=1, key=neg), 2)
|
||||||
|
|
||||||
|
self.assertEqual(min((1, 2), key=None), 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__
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix min and max functions to get default behavior when key is None.
|
|
@ -1639,6 +1639,10 @@ min_max(PyObject *args, PyObject *kwds, int op)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyfunc == Py_None) {
|
||||||
|
keyfunc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
maxitem = NULL; /* the result */
|
maxitem = NULL; /* the result */
|
||||||
maxval = NULL; /* the value associated with the result */
|
maxval = NULL; /* the value associated with the result */
|
||||||
while (( item = PyIter_Next(it) )) {
|
while (( item = PyIter_Next(it) )) {
|
||||||
|
|
Loading…
Reference in New Issue