Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 70b64fc

Browse files
committed
Issue #1771: Remove cmp parameter from list.sort() and builtin.sorted().
1 parent 4f06612 commit 70b64fc

10 files changed

Lines changed: 82 additions & 265 deletions

File tree

Doc/library/functions.rst

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -959,31 +959,20 @@ available. They are listed here in alphabetical order.
959959
``a[start:stop:step]`` or ``a[start:stop, i]``.
960960

961961

962-
.. function:: sorted(iterable[, cmp[, key[, reverse]]])
962+
.. function:: sorted(iterable[, key[, reverse]])
963963

964964
Return a new sorted list from the items in *iterable*.
965965

966-
The optional arguments *cmp*, *key*, and *reverse* have the same meaning as
966+
The optional arguments *key* and *reverse* have the same meaning as
967967
those for the :meth:`list.sort` method (described in section
968968
:ref:`typesseq-mutable`).
969969

970-
*cmp* specifies a custom comparison function of two arguments (iterable
971-
elements) which should return a negative, zero or positive number depending on
972-
whether the first argument is considered smaller than, equal to, or larger than
973-
the second argument: ``cmp=lambda x,y: cmp(x.lower(), y.lower())``. The default
974-
value is ``None``.
975-
976970
*key* specifies a function of one argument that is used to extract a comparison
977971
key from each list element: ``key=str.lower``. The default value is ``None``.
978972

979973
*reverse* is a boolean value. If set to ``True``, then the list elements are
980974
sorted as if each comparison were reversed.
981975

982-
In general, the *key* and *reverse* conversion processes are much faster than
983-
specifying an equivalent *cmp* function. This is because *cmp* is called
984-
multiple times for each list element while *key* and *reverse* touch each
985-
element only once.
986-
987976

988977
.. function:: staticmethod(function)
989978

Doc/library/stdtypes.rst

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1266,8 +1266,7 @@ Note that while lists allow their items to be of any type, bytearray object
12661266
| ``s.reverse()`` | reverses the items of *s* in | \(6) |
12671267
| | place | |
12681268
+------------------------------+--------------------------------+---------------------+
1269-
| ``s.sort([cmp[, key[, | sort the items of *s* in place | (6), (7) |
1270-
| reverse]]])`` | | |
1269+
| ``s.sort([key[, reverse]])`` | sort the items of *s* in place | (6), (7) |
12711270
+------------------------------+--------------------------------+---------------------+
12721271

12731272
.. index::
@@ -1321,23 +1320,12 @@ Notes:
13211320
The :meth:`sort` method takes optional arguments for controlling the
13221321
comparisons.
13231322

1324-
*cmp* specifies a custom comparison function of two arguments (list items) which
1325-
should return a negative, zero or positive number depending on whether the first
1326-
argument is considered smaller than, equal to, or larger than the second
1327-
argument: ``cmp=lambda x,y: cmp(x.lower(), y.lower())``. The default value
1328-
is ``None``.
1329-
13301323
*key* specifies a function of one argument that is used to extract a comparison
13311324
key from each list element: ``key=str.lower``. The default value is ``None``.
13321325

13331326
*reverse* is a boolean value. If set to ``True``, then the list elements are
13341327
sorted as if each comparison were reversed.
13351328

1336-
In general, the *key* and *reverse* conversion processes are much faster than
1337-
specifying an equivalent *cmp* function. This is because *cmp* is called
1338-
multiple times for each list element while *key* and *reverse* touch each
1339-
element only once.
1340-
13411329
Starting with Python 2.3, the :meth:`sort` method is guaranteed to be stable. A
13421330
sort is stable if it guarantees not to change the relative order of elements
13431331
that compare equal --- this is helpful for sorting in multiple passes (for

Lib/cookielib.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,8 +1255,7 @@ def _cookie_attrs(self, cookies):
12551255
12561256
"""
12571257
# add cookies in order of most specific (ie. longest) path first
1258-
def decreasing_size(a, b): return cmp(len(b.path), len(a.path))
1259-
cookies.sort(decreasing_size)
1258+
cookies.sort(key=lambda a: len(a.path), reverse=True)
12601259

12611260
version_set = False
12621261

Lib/pstats.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def sort_stats(self, *field):
238238
stats_list.append((cc, nc, tt, ct) + func +
239239
(func_std_string(func), func))
240240

241-
stats_list.sort(TupleComp(sort_tuple).compare)
241+
stats_list.sort(key=CmpToKey(TupleComp(sort_tuple).compare))
242242

243243
self.fcn_list = fcn_list = []
244244
for tuple in stats_list:
@@ -470,6 +470,16 @@ def compare (self, left, right):
470470
return direction
471471
return 0
472472

473+
def CmpToKey(mycmp):
474+
'Convert a cmp= function into a key= function'
475+
class K(object):
476+
def __init__(self, obj):
477+
self.obj = obj
478+
def __lt__(self, other):
479+
return mycmp(self.obj, other.obj) == -1
480+
return K
481+
482+
473483
#**************************************************************************
474484
# func_name is a triple (file:string, line:int, name:string)
475485

Lib/test/list_tests.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@
88
import unittest
99
from test import test_support, seq_tests
1010

11+
def CmpToKey(mycmp):
12+
'Convert a cmp= function into a key= function'
13+
class K(object):
14+
def __init__(self, obj):
15+
self.obj = obj
16+
def __lt__(self, other):
17+
return mycmp(self.obj, other.obj) == -1
18+
return K
19+
1120
class CommonTest(seq_tests.CommonTest):
1221

1322
def test_init(self):
@@ -430,23 +439,21 @@ def test_sort(self):
430439

431440
def revcmp(a, b):
432441
return cmp(b, a)
433-
u.sort(revcmp)
442+
u.sort(key=CmpToKey(revcmp))
434443
self.assertEqual(u, self.type2test([2,1,0,-1,-2]))
435444

436445
# The following dumps core in unpatched Python 1.5:
437446
def myComparison(x,y):
438447
return cmp(x%3, y%7)
439448
z = self.type2test(range(12))
440-
z.sort(myComparison)
449+
z.sort(key=CmpToKey(myComparison))
441450

442451
self.assertRaises(TypeError, z.sort, 2)
443452

444453
def selfmodifyingComparison(x,y):
445454
z.append(1)
446455
return cmp(x, y)
447-
self.assertRaises(ValueError, z.sort, selfmodifyingComparison)
448-
449-
self.assertRaises(TypeError, z.sort, lambda x, y: 's')
456+
self.assertRaises(ValueError, z.sort, key=CmpToKey(selfmodifyingComparison))
450457

451458
self.assertRaises(TypeError, z.sort, 42, 42, 42, 42)
452459

Lib/test/test_builtin.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,9 +1764,6 @@ def test_basic(self):
17641764

17651765
data.reverse()
17661766
random.shuffle(copy)
1767-
self.assertEqual(data, sorted(copy, cmp=lambda x, y: (x < y) - (x > y)))
1768-
self.assertNotEqual(data, copy)
1769-
random.shuffle(copy)
17701767
self.assertEqual(data, sorted(copy, key=lambda x: -x))
17711768
self.assertNotEqual(data, copy)
17721769
random.shuffle(copy)

Lib/test/test_sort.py

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
verbose = test_support.verbose
77
nerrors = 0
88

9+
def CmpToKey(mycmp):
10+
'Convert a cmp= function into a key= function'
11+
class K(object):
12+
def __init__(self, obj):
13+
self.obj = obj
14+
def __lt__(self, other):
15+
return mycmp(self.obj, other.obj) == -1
16+
return K
17+
918
def check(tag, expected, raw, compare=None):
1019
global nerrors
1120

@@ -14,7 +23,7 @@ def check(tag, expected, raw, compare=None):
1423

1524
orig = raw[:] # save input in case of error
1625
if compare:
17-
raw.sort(compare)
26+
raw.sort(key=CmpToKey(compare))
1827
else:
1928
raw.sort()
2029

@@ -99,7 +108,7 @@ def __repr__(self):
99108
print(" Checking against an insane comparison function.")
100109
print(" If the implementation isn't careful, this may segfault.")
101110
s = x[:]
102-
s.sort(lambda a, b: int(random.random() * 3) - 1)
111+
s.sort(key=CmpToKey(lambda a, b: int(random.random() * 3) - 1))
103112
check("an insane function left some permutation", x, s)
104113

105114
x = [Complains(i) for i in x]
@@ -141,14 +150,6 @@ def __lt__(self, other):
141150
L = [C() for i in range(50)]
142151
self.assertRaises(ValueError, L.sort)
143152

144-
def test_cmpNone(self):
145-
# Testing None as a comparison function.
146-
147-
L = list(range(50))
148-
random.shuffle(L)
149-
L.sort(None)
150-
self.assertEqual(L, list(range(50)))
151-
152153
def test_undetected_mutation(self):
153154
# Python 2.4a1 did not always detect mutation
154155
memorywaster = []
@@ -158,12 +159,12 @@ def mutating_cmp(x, y):
158159
L.pop()
159160
return cmp(x, y)
160161
L = [1,2]
161-
self.assertRaises(ValueError, L.sort, mutating_cmp)
162+
self.assertRaises(ValueError, L.sort, key=CmpToKey(mutating_cmp))
162163
def mutating_cmp(x, y):
163164
L.append(3)
164165
del L[:]
165166
return cmp(x, y)
166-
self.assertRaises(ValueError, L.sort, mutating_cmp)
167+
self.assertRaises(ValueError, L.sort, key=CmpToKey(mutating_cmp))
167168
memorywaster = [memorywaster]
168169

169170
#==============================================================================
@@ -175,11 +176,11 @@ def test_decorated(self):
175176
copy = data[:]
176177
random.shuffle(data)
177178
data.sort(key=str.lower)
178-
copy.sort(cmp=lambda x,y: cmp(x.lower(), y.lower()))
179+
copy.sort(key=CmpToKey(lambda x,y: cmp(x.lower(), y.lower())))
179180

180181
def test_baddecorator(self):
181182
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
182-
self.assertRaises(TypeError, data.sort, None, lambda x,y: 0)
183+
self.assertRaises(TypeError, data.sort, key=lambda x,y: 0)
183184

184185
def test_stability(self):
185186
data = [(random.randrange(100), i) for i in range(200)]
@@ -188,25 +189,11 @@ def test_stability(self):
188189
copy.sort() # sort using both fields
189190
self.assertEqual(data, copy) # should get the same result
190191

191-
def test_cmp_and_key_combination(self):
192-
# Verify that the wrapper has been removed
193-
def compare(x, y):
194-
self.assertEqual(type(x), str)
195-
self.assertEqual(type(x), str)
196-
return cmp(x, y)
197-
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
198-
data.sort(cmp=compare, key=str.lower)
199-
200-
def test_badcmp_with_key(self):
201-
# Verify that the wrapper has been removed
202-
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
203-
self.assertRaises(TypeError, data.sort, "bad", str.lower)
204-
205192
def test_key_with_exception(self):
206193
# Verify that the wrapper has been removed
207194
data = list(range(-2, 2))
208195
dup = data[:]
209-
self.assertRaises(ZeroDivisionError, data.sort, None, lambda x: 1/x)
196+
self.assertRaises(ZeroDivisionError, data.sort, key=lambda x: 1/x)
210197
self.assertEqual(data, dup)
211198

212199
def test_key_with_mutation(self):
@@ -254,14 +241,13 @@ def test_reverse(self):
254241
random.shuffle(data)
255242
data.sort(reverse=True)
256243
self.assertEqual(data, list(range(99,-1,-1)))
257-
self.assertRaises(TypeError, data.sort, "wrong type")
258244

259245
def test_reverse_stability(self):
260246
data = [(random.randrange(100), i) for i in range(200)]
261247
copy1 = data[:]
262248
copy2 = data[:]
263-
data.sort(cmp=lambda x,y: cmp(x[0],y[0]), reverse=True)
264-
copy1.sort(cmp=lambda x,y: cmp(y[0],x[0]))
249+
data.sort(key=CmpToKey(lambda x,y: cmp(x[0],y[0])), reverse=True)
250+
copy1.sort(key=CmpToKey(lambda x,y: cmp(y[0],x[0])))
265251
self.assertEqual(data, copy1)
266252
copy2.sort(key=lambda x: x[0], reverse=True)
267253
self.assertEqual(data, copy2)

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Core and Builtins
1414

1515
- Issue #1973: bytes.fromhex('') raises SystemError
1616

17+
- Issue #1771: remove cmp parameter from sorted() and list.sort()
18+
1719
- Issue #1969: split and rsplit in bytearray are inconsistent
1820

1921
- map() and itertools.imap() no longer accept None for the first argument.

0 commit comments

Comments
 (0)