Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
70b64fce
Kaydet (Commit)
70b64fce
authored
Ock 30, 2008
tarafından
Raymond Hettinger
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #1771: Remove cmp parameter from list.sort() and builtin.sorted().
üst
4f066126
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
82 additions
and
265 deletions
+82
-265
functions.rst
Doc/library/functions.rst
+2
-13
stdtypes.rst
Doc/library/stdtypes.rst
+1
-13
cookielib.py
Lib/cookielib.py
+1
-2
pstats.py
Lib/pstats.py
+11
-1
list_tests.py
Lib/test/list_tests.py
+12
-5
test_builtin.py
Lib/test/test_builtin.py
+0
-3
test_sort.py
Lib/test/test_sort.py
+18
-32
NEWS
Misc/NEWS
+2
-0
listobject.c
Objects/listobject.c
+29
-190
bltinmodule.c
Python/bltinmodule.c
+6
-6
No files found.
Doc/library/functions.rst
Dosyayı görüntüle @
70b64fce
...
...
@@ -959,31 +959,20 @@ available. They are listed here in alphabetical order.
``a[start:stop:step]`` or ``a[start:stop, i]``.
.. function:: sorted(iterable[,
cmp[, key[, reverse]
]])
.. function:: sorted(iterable[,
key[, reverse
]])
Return a new sorted list from the items in *iterable*.
The optional arguments *
cmp*, *key*,
and *reverse* have the same meaning as
The optional arguments *
key*
and *reverse* have the same meaning as
those for the :meth:`list.sort` method (described in section
:ref:`typesseq-mutable`).
*cmp* specifies a custom comparison function of two arguments (iterable
elements) which should return a negative, zero or positive number depending on
whether the first argument is considered smaller than, equal to, or larger than
the second argument: ``cmp=lambda x,y: cmp(x.lower(), y.lower())``. The default
value is ``None``.
*key* specifies a function of one argument that is used to extract a comparison
key from each list element: ``key=str.lower``. The default value is ``None``.
*reverse* is a boolean value. If set to ``True``, then the list elements are
sorted as if each comparison were reversed.
In general, the *key* and *reverse* conversion processes are much faster than
specifying an equivalent *cmp* function. This is because *cmp* is called
multiple times for each list element while *key* and *reverse* touch each
element only once.
.. function:: staticmethod(function)
...
...
Doc/library/stdtypes.rst
Dosyayı görüntüle @
70b64fce
...
...
@@ -1266,8 +1266,7 @@ Note that while lists allow their items to be of any type, bytearray object
| ``s.reverse()`` | reverses the items of *s* in | \(6) |
| | place | |
+------------------------------+--------------------------------+---------------------+
| ``s.sort([cmp[, key[, | sort the items of *s* in place | (6), (7) |
| reverse]]])`` | | |
| ``s.sort([key[, reverse]])`` | sort the items of *s* in place | (6), (7) |
+------------------------------+--------------------------------+---------------------+
.. index::
...
...
@@ -1321,23 +1320,12 @@ Notes:
The :meth:`sort` method takes optional arguments for controlling the
comparisons.
*cmp* specifies a custom comparison function of two arguments (list items) which
should return a negative, zero or positive number depending on whether the first
argument is considered smaller than, equal to, or larger than the second
argument: ``cmp=lambda x,y: cmp(x.lower(), y.lower())``. The default value
is ``None``.
*key* specifies a function of one argument that is used to extract a comparison
key from each list element: ``key=str.lower``. The default value is ``None``.
*reverse* is a boolean value. If set to ``True``, then the list elements are
sorted as if each comparison were reversed.
In general, the *key* and *reverse* conversion processes are much faster than
specifying an equivalent *cmp* function. This is because *cmp* is called
multiple times for each list element while *key* and *reverse* touch each
element only once.
Starting with Python 2.3, the :meth:`sort` method is guaranteed to be stable. A
sort is stable if it guarantees not to change the relative order of elements
that compare equal --- this is helpful for sorting in multiple passes (for
...
...
Lib/cookielib.py
Dosyayı görüntüle @
70b64fce
...
...
@@ -1255,8 +1255,7 @@ class CookieJar:
"""
# add cookies in order of most specific (ie. longest) path first
def
decreasing_size
(
a
,
b
):
return
cmp
(
len
(
b
.
path
),
len
(
a
.
path
))
cookies
.
sort
(
decreasing_size
)
cookies
.
sort
(
key
=
lambda
a
:
len
(
a
.
path
),
reverse
=
True
)
version_set
=
False
...
...
Lib/pstats.py
Dosyayı görüntüle @
70b64fce
...
...
@@ -238,7 +238,7 @@ class Stats:
stats_list
.
append
((
cc
,
nc
,
tt
,
ct
)
+
func
+
(
func_std_string
(
func
),
func
))
stats_list
.
sort
(
TupleComp
(
sort_tuple
)
.
compare
)
stats_list
.
sort
(
key
=
CmpToKey
(
TupleComp
(
sort_tuple
)
.
compare
)
)
self
.
fcn_list
=
fcn_list
=
[]
for
tuple
in
stats_list
:
...
...
@@ -470,6 +470,16 @@ class TupleComp:
return
direction
return
0
def
CmpToKey
(
mycmp
):
'Convert a cmp= function into a key= function'
class
K
(
object
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
def
__lt__
(
self
,
other
):
return
mycmp
(
self
.
obj
,
other
.
obj
)
==
-
1
return
K
#**************************************************************************
# func_name is a triple (file:string, line:int, name:string)
...
...
Lib/test/list_tests.py
Dosyayı görüntüle @
70b64fce
...
...
@@ -8,6 +8,15 @@ import os
import
unittest
from
test
import
test_support
,
seq_tests
def
CmpToKey
(
mycmp
):
'Convert a cmp= function into a key= function'
class
K
(
object
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
def
__lt__
(
self
,
other
):
return
mycmp
(
self
.
obj
,
other
.
obj
)
==
-
1
return
K
class
CommonTest
(
seq_tests
.
CommonTest
):
def
test_init
(
self
):
...
...
@@ -430,23 +439,21 @@ class CommonTest(seq_tests.CommonTest):
def
revcmp
(
a
,
b
):
return
cmp
(
b
,
a
)
u
.
sort
(
revcmp
)
u
.
sort
(
key
=
CmpToKey
(
revcmp
)
)
self
.
assertEqual
(
u
,
self
.
type2test
([
2
,
1
,
0
,
-
1
,
-
2
]))
# The following dumps core in unpatched Python 1.5:
def
myComparison
(
x
,
y
):
return
cmp
(
x
%
3
,
y
%
7
)
z
=
self
.
type2test
(
range
(
12
))
z
.
sort
(
myComparison
)
z
.
sort
(
key
=
CmpToKey
(
myComparison
)
)
self
.
assertRaises
(
TypeError
,
z
.
sort
,
2
)
def
selfmodifyingComparison
(
x
,
y
):
z
.
append
(
1
)
return
cmp
(
x
,
y
)
self
.
assertRaises
(
ValueError
,
z
.
sort
,
selfmodifyingComparison
)
self
.
assertRaises
(
TypeError
,
z
.
sort
,
lambda
x
,
y
:
's'
)
self
.
assertRaises
(
ValueError
,
z
.
sort
,
key
=
CmpToKey
(
selfmodifyingComparison
))
self
.
assertRaises
(
TypeError
,
z
.
sort
,
42
,
42
,
42
,
42
)
...
...
Lib/test/test_builtin.py
Dosyayı görüntüle @
70b64fce
...
...
@@ -1764,9 +1764,6 @@ class TestSorted(unittest.TestCase):
data
.
reverse
()
random
.
shuffle
(
copy
)
self
.
assertEqual
(
data
,
sorted
(
copy
,
cmp
=
lambda
x
,
y
:
(
x
<
y
)
-
(
x
>
y
)))
self
.
assertNotEqual
(
data
,
copy
)
random
.
shuffle
(
copy
)
self
.
assertEqual
(
data
,
sorted
(
copy
,
key
=
lambda
x
:
-
x
))
self
.
assertNotEqual
(
data
,
copy
)
random
.
shuffle
(
copy
)
...
...
Lib/test/test_sort.py
Dosyayı görüntüle @
70b64fce
...
...
@@ -6,6 +6,15 @@ import unittest
verbose
=
test_support
.
verbose
nerrors
=
0
def
CmpToKey
(
mycmp
):
'Convert a cmp= function into a key= function'
class
K
(
object
):
def
__init__
(
self
,
obj
):
self
.
obj
=
obj
def
__lt__
(
self
,
other
):
return
mycmp
(
self
.
obj
,
other
.
obj
)
==
-
1
return
K
def
check
(
tag
,
expected
,
raw
,
compare
=
None
):
global
nerrors
...
...
@@ -14,7 +23,7 @@ def check(tag, expected, raw, compare=None):
orig
=
raw
[:]
# save input in case of error
if
compare
:
raw
.
sort
(
compare
)
raw
.
sort
(
key
=
CmpToKey
(
compare
)
)
else
:
raw
.
sort
()
...
...
@@ -99,7 +108,7 @@ class TestBase(unittest.TestCase):
print
(
" Checking against an insane comparison function."
)
print
(
" If the implementation isn't careful, this may segfault."
)
s
=
x
[:]
s
.
sort
(
lambda
a
,
b
:
int
(
random
.
random
()
*
3
)
-
1
)
s
.
sort
(
key
=
CmpToKey
(
lambda
a
,
b
:
int
(
random
.
random
()
*
3
)
-
1
)
)
check
(
"an insane function left some permutation"
,
x
,
s
)
x
=
[
Complains
(
i
)
for
i
in
x
]
...
...
@@ -141,14 +150,6 @@ class TestBugs(unittest.TestCase):
L
=
[
C
()
for
i
in
range
(
50
)]
self
.
assertRaises
(
ValueError
,
L
.
sort
)
def
test_cmpNone
(
self
):
# Testing None as a comparison function.
L
=
list
(
range
(
50
))
random
.
shuffle
(
L
)
L
.
sort
(
None
)
self
.
assertEqual
(
L
,
list
(
range
(
50
)))
def
test_undetected_mutation
(
self
):
# Python 2.4a1 did not always detect mutation
memorywaster
=
[]
...
...
@@ -158,12 +159,12 @@ class TestBugs(unittest.TestCase):
L
.
pop
()
return
cmp
(
x
,
y
)
L
=
[
1
,
2
]
self
.
assertRaises
(
ValueError
,
L
.
sort
,
mutating_cmp
)
self
.
assertRaises
(
ValueError
,
L
.
sort
,
key
=
CmpToKey
(
mutating_cmp
)
)
def
mutating_cmp
(
x
,
y
):
L
.
append
(
3
)
del
L
[:]
return
cmp
(
x
,
y
)
self
.
assertRaises
(
ValueError
,
L
.
sort
,
mutating_cmp
)
self
.
assertRaises
(
ValueError
,
L
.
sort
,
key
=
CmpToKey
(
mutating_cmp
)
)
memorywaster
=
[
memorywaster
]
#==============================================================================
...
...
@@ -175,11 +176,11 @@ class TestDecorateSortUndecorate(unittest.TestCase):
copy
=
data
[:]
random
.
shuffle
(
data
)
data
.
sort
(
key
=
str
.
lower
)
copy
.
sort
(
cmp
=
lambda
x
,
y
:
cmp
(
x
.
lower
(),
y
.
lower
(
)))
copy
.
sort
(
key
=
CmpToKey
(
lambda
x
,
y
:
cmp
(
x
.
lower
(),
y
.
lower
()
)))
def
test_baddecorator
(
self
):
data
=
'The quick Brown fox Jumped over The lazy Dog'
.
split
()
self
.
assertRaises
(
TypeError
,
data
.
sort
,
None
,
lambda
x
,
y
:
0
)
self
.
assertRaises
(
TypeError
,
data
.
sort
,
key
=
lambda
x
,
y
:
0
)
def
test_stability
(
self
):
data
=
[(
random
.
randrange
(
100
),
i
)
for
i
in
range
(
200
)]
...
...
@@ -188,25 +189,11 @@ class TestDecorateSortUndecorate(unittest.TestCase):
copy
.
sort
()
# sort using both fields
self
.
assertEqual
(
data
,
copy
)
# should get the same result
def
test_cmp_and_key_combination
(
self
):
# Verify that the wrapper has been removed
def
compare
(
x
,
y
):
self
.
assertEqual
(
type
(
x
),
str
)
self
.
assertEqual
(
type
(
x
),
str
)
return
cmp
(
x
,
y
)
data
=
'The quick Brown fox Jumped over The lazy Dog'
.
split
()
data
.
sort
(
cmp
=
compare
,
key
=
str
.
lower
)
def
test_badcmp_with_key
(
self
):
# Verify that the wrapper has been removed
data
=
'The quick Brown fox Jumped over The lazy Dog'
.
split
()
self
.
assertRaises
(
TypeError
,
data
.
sort
,
"bad"
,
str
.
lower
)
def
test_key_with_exception
(
self
):
# Verify that the wrapper has been removed
data
=
list
(
range
(
-
2
,
2
))
dup
=
data
[:]
self
.
assertRaises
(
ZeroDivisionError
,
data
.
sort
,
None
,
lambda
x
:
1
/
x
)
self
.
assertRaises
(
ZeroDivisionError
,
data
.
sort
,
key
=
lambda
x
:
1
/
x
)
self
.
assertEqual
(
data
,
dup
)
def
test_key_with_mutation
(
self
):
...
...
@@ -254,14 +241,13 @@ class TestDecorateSortUndecorate(unittest.TestCase):
random
.
shuffle
(
data
)
data
.
sort
(
reverse
=
True
)
self
.
assertEqual
(
data
,
list
(
range
(
99
,
-
1
,
-
1
)))
self
.
assertRaises
(
TypeError
,
data
.
sort
,
"wrong type"
)
def
test_reverse_stability
(
self
):
data
=
[(
random
.
randrange
(
100
),
i
)
for
i
in
range
(
200
)]
copy1
=
data
[:]
copy2
=
data
[:]
data
.
sort
(
cmp
=
lambda
x
,
y
:
cmp
(
x
[
0
],
y
[
0
]
),
reverse
=
True
)
copy1
.
sort
(
cmp
=
lambda
x
,
y
:
cmp
(
y
[
0
],
x
[
0
]
))
data
.
sort
(
key
=
CmpToKey
(
lambda
x
,
y
:
cmp
(
x
[
0
],
y
[
0
])
),
reverse
=
True
)
copy1
.
sort
(
key
=
CmpToKey
(
lambda
x
,
y
:
cmp
(
y
[
0
],
x
[
0
])
))
self
.
assertEqual
(
data
,
copy1
)
copy2
.
sort
(
key
=
lambda
x
:
x
[
0
],
reverse
=
True
)
self
.
assertEqual
(
data
,
copy2
)
...
...
Misc/NEWS
Dosyayı görüntüle @
70b64fce
...
...
@@ -14,6 +14,8 @@ Core and Builtins
- Issue #1973: bytes.fromhex('') raises SystemError
- Issue #1771: remove cmp parameter from sorted() and list.sort()
- Issue #1969: split and rsplit in bytearray are inconsistent
- map() and itertools.imap() no longer accept None for the first argument.
...
...
Objects/listobject.c
Dosyayı görüntüle @
70b64fce
...
...
@@ -888,64 +888,17 @@ reverse_slice(PyObject **lo, PyObject **hi)
* pieces to this algorithm; read listsort.txt for overviews and details.
*/
/* Comparison function. Takes care of calling a user-supplied
* comparison function (any callable Python object), which must not be
* NULL (use the ISLT macro if you don't know, or call PyObject_RichCompareBool
* with Py_LT if you know it's NULL).
/* Comparison function: PyObject_RichCompareBool with Py_LT.
* Returns -1 on error, 1 if x < y, 0 if x >= y.
*/
static
int
islt
(
PyObject
*
x
,
PyObject
*
y
,
PyObject
*
compare
)
{
PyObject
*
res
;
PyObject
*
args
;
Py_ssize_t
i
;
assert
(
compare
!=
NULL
);
/* Call the user's comparison function and translate the 3-way
* result into true or false (or error).
*/
args
=
PyTuple_New
(
2
);
if
(
args
==
NULL
)
return
-
1
;
Py_INCREF
(
x
);
Py_INCREF
(
y
);
PyTuple_SET_ITEM
(
args
,
0
,
x
);
PyTuple_SET_ITEM
(
args
,
1
,
y
);
res
=
PyObject_Call
(
compare
,
args
,
NULL
);
Py_DECREF
(
args
);
if
(
res
==
NULL
)
return
-
1
;
if
(
!
PyLong_CheckExact
(
res
))
{
PyErr_Format
(
PyExc_TypeError
,
"comparison function must return int, not %.200s"
,
res
->
ob_type
->
tp_name
);
Py_DECREF
(
res
);
return
-
1
;
}
i
=
PyLong_AsLong
(
res
);
Py_DECREF
(
res
);
if
(
i
==
-
1
&&
PyErr_Occurred
())
{
/* Overflow in long conversion. */
return
-
1
;
}
return
i
<
0
;
}
/* If COMPARE is NULL, calls PyObject_RichCompareBool with Py_LT, else calls
* islt. This avoids a layer of function call in the usual case, and
* sorting does many comparisons.
* Returns -1 on error, 1 if x < y, 0 if x >= y.
*/
#define ISLT(X, Y, COMPARE) ((COMPARE) == NULL ? \
PyObject_RichCompareBool(X, Y, Py_LT) : \
islt(X, Y, COMPARE))
#define ISLT(X, Y) (PyObject_RichCompareBool(X, Y, Py_LT))
/* Compare X to Y via "<". Goto "fail" if the comparison raises an
error. Else "k" is set to true iff X<Y, and an "if (k)" block is
started. It makes more sense in context <wink>. X and Y are PyObject*s.
*/
#define IFLT(X, Y) if ((k = ISLT(X, Y
, compare
)) < 0) goto fail; \
#define IFLT(X, Y) if ((k = ISLT(X, Y)) < 0) goto fail; \
if (k)
/* binarysort is the best method for sorting small arrays: it does
...
...
@@ -960,8 +913,7 @@ islt(PyObject *x, PyObject *y, PyObject *compare)
the input (nothing is lost or duplicated).
*/
static
int
binarysort
(
PyObject
**
lo
,
PyObject
**
hi
,
PyObject
**
start
,
PyObject
*
compare
)
/* compare -- comparison function object, or NULL for default */
binarysort
(
PyObject
**
lo
,
PyObject
**
hi
,
PyObject
**
start
)
{
register
Py_ssize_t
k
;
register
PyObject
**
l
,
**
p
,
**
r
;
...
...
@@ -1026,7 +978,7 @@ elements to get out of order).
Returns -1 in case of error.
*/
static
Py_ssize_t
count_run
(
PyObject
**
lo
,
PyObject
**
hi
,
PyObject
*
compare
,
int
*
descending
)
count_run
(
PyObject
**
lo
,
PyObject
**
hi
,
int
*
descending
)
{
Py_ssize_t
k
;
Py_ssize_t
n
;
...
...
@@ -1081,7 +1033,7 @@ key, and the last n-k should follow key.
Returns -1 on error. See listsort.txt for info on the method.
*/
static
Py_ssize_t
gallop_left
(
PyObject
*
key
,
PyObject
**
a
,
Py_ssize_t
n
,
Py_ssize_t
hint
,
PyObject
*
compare
)
gallop_left
(
PyObject
*
key
,
PyObject
**
a
,
Py_ssize_t
n
,
Py_ssize_t
hint
)
{
Py_ssize_t
ofs
;
Py_ssize_t
lastofs
;
...
...
@@ -1172,7 +1124,7 @@ we're sticking to "<" comparisons that it's much harder to follow if
written as one routine with yet another "left or right?" flag.
*/
static
Py_ssize_t
gallop_right
(
PyObject
*
key
,
PyObject
**
a
,
Py_ssize_t
n
,
Py_ssize_t
hint
,
PyObject
*
compare
)
gallop_right
(
PyObject
*
key
,
PyObject
**
a
,
Py_ssize_t
n
,
Py_ssize_t
hint
)
{
Py_ssize_t
ofs
;
Py_ssize_t
lastofs
;
...
...
@@ -1273,9 +1225,6 @@ struct s_slice {
};
typedef
struct
s_MergeState
{
/* The user-supplied comparison function. or NULL if none given. */
PyObject
*
compare
;
/* This controls when we get *into* galloping mode. It's initialized
* to MIN_GALLOP. merge_lo and merge_hi tend to nudge it higher for
* random data, and lower for highly structured data.
...
...
@@ -1306,10 +1255,9 @@ typedef struct s_MergeState {
/* Conceptually a MergeState's constructor. */
static
void
merge_init
(
MergeState
*
ms
,
PyObject
*
compare
)
merge_init
(
MergeState
*
ms
)
{
assert
(
ms
!=
NULL
);
ms
->
compare
=
compare
;
ms
->
a
=
ms
->
temparray
;
ms
->
alloced
=
MERGESTATE_TEMP_SIZE
;
ms
->
n
=
0
;
...
...
@@ -1366,7 +1314,6 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
PyObject
**
pb
,
Py_ssize_t
nb
)
{
Py_ssize_t
k
;
PyObject
*
compare
;
PyObject
**
dest
;
int
result
=
-
1
;
/* guilty until proved innocent */
Py_ssize_t
min_gallop
;
...
...
@@ -1386,7 +1333,6 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
goto
CopyB
;
min_gallop
=
ms
->
min_gallop
;
compare
=
ms
->
compare
;
for
(;;)
{
Py_ssize_t
acount
=
0
;
/* # of times A won in a row */
Py_ssize_t
bcount
=
0
;
/* # of times B won in a row */
...
...
@@ -1396,7 +1342,7 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
*/
for
(;;)
{
assert
(
na
>
1
&&
nb
>
0
);
k
=
ISLT
(
*
pb
,
*
pa
,
compare
);
k
=
ISLT
(
*
pb
,
*
pa
);
if
(
k
)
{
if
(
k
<
0
)
goto
Fail
;
...
...
@@ -1431,7 +1377,7 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
assert
(
na
>
1
&&
nb
>
0
);
min_gallop
-=
min_gallop
>
1
;
ms
->
min_gallop
=
min_gallop
;
k
=
gallop_right
(
*
pb
,
pa
,
na
,
0
,
compare
);
k
=
gallop_right
(
*
pb
,
pa
,
na
,
0
);
acount
=
k
;
if
(
k
)
{
if
(
k
<
0
)
...
...
@@ -1454,7 +1400,7 @@ merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
if
(
nb
==
0
)
goto
Succeed
;
k
=
gallop_left
(
*
pa
,
pb
,
nb
,
0
,
compare
);
k
=
gallop_left
(
*
pa
,
pb
,
nb
,
0
);
bcount
=
k
;
if
(
k
)
{
if
(
k
<
0
)
...
...
@@ -1498,7 +1444,6 @@ static Py_ssize_t
merge_hi
(
MergeState
*
ms
,
PyObject
**
pa
,
Py_ssize_t
na
,
PyObject
**
pb
,
Py_ssize_t
nb
)
{
Py_ssize_t
k
;
PyObject
*
compare
;
PyObject
**
dest
;
int
result
=
-
1
;
/* guilty until proved innocent */
PyObject
**
basea
;
...
...
@@ -1523,7 +1468,6 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t
goto
CopyA
;
min_gallop
=
ms
->
min_gallop
;
compare
=
ms
->
compare
;
for
(;;)
{
Py_ssize_t
acount
=
0
;
/* # of times A won in a row */
Py_ssize_t
bcount
=
0
;
/* # of times B won in a row */
...
...
@@ -1533,7 +1477,7 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t
*/
for
(;;)
{
assert
(
na
>
0
&&
nb
>
1
);
k
=
ISLT
(
*
pb
,
*
pa
,
compare
);
k
=
ISLT
(
*
pb
,
*
pa
);
if
(
k
)
{
if
(
k
<
0
)
goto
Fail
;
...
...
@@ -1568,7 +1512,7 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t
assert
(
na
>
0
&&
nb
>
1
);
min_gallop
-=
min_gallop
>
1
;
ms
->
min_gallop
=
min_gallop
;
k
=
gallop_right
(
*
pb
,
basea
,
na
,
na
-
1
,
compare
);
k
=
gallop_right
(
*
pb
,
basea
,
na
,
na
-
1
);
if
(
k
<
0
)
goto
Fail
;
k
=
na
-
k
;
...
...
@@ -1586,7 +1530,7 @@ merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t
if
(
nb
==
1
)
goto
CopyA
;
k
=
gallop_left
(
*
pa
,
baseb
,
nb
,
nb
-
1
,
compare
);
k
=
gallop_left
(
*
pa
,
baseb
,
nb
,
nb
-
1
);
if
(
k
<
0
)
goto
Fail
;
k
=
nb
-
k
;
...
...
@@ -1638,7 +1582,6 @@ merge_at(MergeState *ms, Py_ssize_t i)
PyObject
**
pa
,
**
pb
;
Py_ssize_t
na
,
nb
;
Py_ssize_t
k
;
PyObject
*
compare
;
assert
(
ms
!=
NULL
);
assert
(
ms
->
n
>=
2
);
...
...
@@ -1664,8 +1607,7 @@ merge_at(MergeState *ms, Py_ssize_t i)
/* Where does b start in a? Elements in a before that can be
* ignored (already in place).
*/
compare
=
ms
->
compare
;
k
=
gallop_right
(
*
pb
,
pa
,
na
,
0
,
compare
);
k
=
gallop_right
(
*
pb
,
pa
,
na
,
0
);
if
(
k
<
0
)
return
-
1
;
pa
+=
k
;
...
...
@@ -1676,7 +1618,7 @@ merge_at(MergeState *ms, Py_ssize_t i)
/* Where does a end in b? Elements in b after that can be
* ignored (already in place).
*/
nb
=
gallop_left
(
pa
[
na
-
1
],
pb
,
nb
,
nb
-
1
,
compare
);
nb
=
gallop_left
(
pa
[
na
-
1
],
pb
,
nb
,
nb
-
1
);
if
(
nb
<=
0
)
return
nb
;
...
...
@@ -1771,8 +1713,8 @@ merge_compute_minrun(Py_ssize_t n)
pattern. Holds a key which is used for comparisons and the original record
which is returned during the undecorate phase. By exposing only the key
during comparisons, the underlying sort stability characteristics are left
unchanged. Also,
if a custom comparison function is used, it will only see
the key instead of
a full record. */
unchanged. Also,
the comparison function will only see the key instead of
a full record. */
typedef
struct
{
PyObject_HEAD
...
...
@@ -1866,104 +1808,6 @@ sortwrapper_getvalue(PyObject *so)
return
value
;
}
/* Wrapper for user specified cmp functions in combination with a
specified key function. Makes sure the cmp function is presented
with the actual key instead of the sortwrapper */
typedef
struct
{
PyObject_HEAD
PyObject
*
func
;
}
cmpwrapperobject
;
static
void
cmpwrapper_dealloc
(
cmpwrapperobject
*
co
)
{
Py_XDECREF
(
co
->
func
);
PyObject_Del
(
co
);
}
static
PyObject
*
cmpwrapper_call
(
cmpwrapperobject
*
co
,
PyObject
*
args
,
PyObject
*
kwds
)
{
PyObject
*
x
,
*
y
,
*
xx
,
*
yy
;
if
(
!
PyArg_UnpackTuple
(
args
,
""
,
2
,
2
,
&
x
,
&
y
))
return
NULL
;
if
(
!
PyObject_TypeCheck
(
x
,
&
PySortWrapper_Type
)
||
!
PyObject_TypeCheck
(
y
,
&
PySortWrapper_Type
))
{
PyErr_SetString
(
PyExc_TypeError
,
"expected a sortwrapperobject"
);
return
NULL
;
}
xx
=
((
sortwrapperobject
*
)
x
)
->
key
;
yy
=
((
sortwrapperobject
*
)
y
)
->
key
;
return
PyObject_CallFunctionObjArgs
(
co
->
func
,
xx
,
yy
,
NULL
);
}
PyDoc_STRVAR
(
cmpwrapper_doc
,
"cmp() wrapper for sort with custom keys."
);
PyTypeObject
PyCmpWrapper_Type
=
{
PyVarObject_HEAD_INIT
(
&
PyType_Type
,
0
)
"cmpwrapper"
,
/* tp_name */
sizeof
(
cmpwrapperobject
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
(
destructor
)
cmpwrapper_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
(
ternaryfunc
)
cmpwrapper_call
,
/* tp_call */
0
,
/* tp_str */
PyObject_GenericGetAttr
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
,
/* tp_flags */
cmpwrapper_doc
,
/* tp_doc */
};
static
PyObject
*
build_cmpwrapper
(
PyObject
*
cmpfunc
)
{
cmpwrapperobject
*
co
;
co
=
PyObject_New
(
cmpwrapperobject
,
&
PyCmpWrapper_Type
);
if
(
co
==
NULL
)
return
NULL
;
Py_INCREF
(
cmpfunc
);
co
->
func
=
cmpfunc
;
return
(
PyObject
*
)
co
;
}
static
int
is_default_cmp
(
PyObject
*
cmpfunc
)
{
PyCFunctionObject
*
f
;
const
char
*
module
;
if
(
cmpfunc
==
NULL
||
cmpfunc
==
Py_None
)
return
1
;
if
(
!
PyCFunction_Check
(
cmpfunc
))
return
0
;
f
=
(
PyCFunctionObject
*
)
cmpfunc
;
if
(
f
->
m_self
!=
NULL
)
return
0
;
if
(
!
PyUnicode_Check
(
f
->
m_module
))
return
0
;
module
=
PyUnicode_AsString
(
f
->
m_module
);
if
(
module
==
NULL
)
return
0
;
if
(
strcmp
(
module
,
"builtins"
)
!=
0
)
return
0
;
if
(
strcmp
(
f
->
m_ml
->
ml_name
,
"cmp"
)
!=
0
)
return
0
;
return
1
;
}
/* An adaptive, stable, natural mergesort. See listsort.txt.
* Returns Py_None on success, NULL on error. Even in case of error, the
* list will be some permutation of its input state (nothing is lost or
...
...
@@ -1979,31 +1823,27 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t
saved_ob_size
,
saved_allocated
;
PyObject
**
saved_ob_item
;
PyObject
**
final_ob_item
;
PyObject
*
compare
=
NULL
;
PyObject
*
result
=
NULL
;
/* guilty until proved innocent */
int
reverse
=
0
;
PyObject
*
keyfunc
=
NULL
;
Py_ssize_t
i
;
PyObject
*
key
,
*
value
,
*
kvpair
;
static
char
*
kwlist
[]
=
{
"
cmp"
,
"
key"
,
"reverse"
,
0
};
static
char
*
kwlist
[]
=
{
"key"
,
"reverse"
,
0
};
assert
(
self
!=
NULL
);
assert
(
PyList_Check
(
self
));
if
(
args
!=
NULL
)
{
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"|OOi:sort"
,
kwlist
,
&
compare
,
&
keyfunc
,
&
reverse
))
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"|Oi:sort"
,
kwlist
,
&
keyfunc
,
&
reverse
))
return
NULL
;
if
(
Py_SIZE
(
args
)
>
0
)
{
PyErr_SetString
(
PyExc_TypeError
,
"must use keyword argument for key function"
);
return
NULL
;
}
}
if
(
is_default_cmp
(
compare
))
compare
=
NULL
;
if
(
keyfunc
==
Py_None
)
keyfunc
=
NULL
;
if
(
compare
!=
NULL
&&
keyfunc
!=
NULL
)
{
compare
=
build_cmpwrapper
(
compare
);
if
(
compare
==
NULL
)
return
NULL
;
}
else
Py_XINCREF
(
compare
);
/* The list is temporarily made empty, so that mutations performed
* by comparison functions can't affect the slice of memory we're
...
...
@@ -2043,7 +1883,7 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
if
(
reverse
&&
saved_ob_size
>
1
)
reverse_slice
(
saved_ob_item
,
saved_ob_item
+
saved_ob_size
);
merge_init
(
&
ms
,
compare
);
merge_init
(
&
ms
);
nremaining
=
saved_ob_size
;
if
(
nremaining
<
2
)
...
...
@@ -2060,7 +1900,7 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
Py_ssize_t
n
;
/* Identify next run. */
n
=
count_run
(
lo
,
hi
,
compare
,
&
descending
);
n
=
count_run
(
lo
,
hi
,
&
descending
);
if
(
n
<
0
)
goto
fail
;
if
(
descending
)
...
...
@@ -2069,7 +1909,7 @@ listsort(PyListObject *self, PyObject *args, PyObject *kwds)
if
(
n
<
minrun
)
{
const
Py_ssize_t
force
=
nremaining
<=
minrun
?
nremaining
:
minrun
;
if
(
binarysort
(
lo
,
lo
+
force
,
lo
+
n
,
compare
)
<
0
)
if
(
binarysort
(
lo
,
lo
+
force
,
lo
+
n
)
<
0
)
goto
fail
;
n
=
force
;
}
...
...
@@ -2131,7 +1971,6 @@ dsu_fail:
}
PyMem_FREE
(
final_ob_item
);
}
Py_XDECREF
(
compare
);
Py_XINCREF
(
result
);
return
result
;
}
...
...
Python/bltinmodule.c
Dosyayı görüntüle @
70b64fce
...
...
@@ -1494,14 +1494,14 @@ Precision may be negative.");
static
PyObject
*
builtin_sorted
(
PyObject
*
self
,
PyObject
*
args
,
PyObject
*
kwds
)
{
PyObject
*
newlist
,
*
v
,
*
seq
,
*
compare
=
NULL
,
*
keyfunc
=
NULL
,
*
newargs
;
PyObject
*
newlist
,
*
v
,
*
seq
,
*
keyfunc
=
NULL
,
*
newargs
;
PyObject
*
callable
;
static
char
*
kwlist
[]
=
{
"iterable"
,
"
cmp"
,
"
key"
,
"reverse"
,
0
};
static
char
*
kwlist
[]
=
{
"iterable"
,
"key"
,
"reverse"
,
0
};
int
reverse
;
/* args 1-
4
should match listsort in Objects/listobject.c */
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|O
O
i:sorted"
,
kwlist
,
&
seq
,
&
compare
,
&
keyfunc
,
&
reverse
))
/* args 1-
3
should match listsort in Objects/listobject.c */
if
(
!
PyArg_ParseTupleAndKeywords
(
args
,
kwds
,
"O|Oi:sorted"
,
kwlist
,
&
seq
,
&
keyfunc
,
&
reverse
))
return
NULL
;
newlist
=
PySequence_List
(
seq
);
...
...
@@ -1533,7 +1533,7 @@ builtin_sorted(PyObject *self, PyObject *args, PyObject *kwds)
}
PyDoc_STRVAR
(
sorted_doc
,
"sorted(iterable,
cmp=None,
key=None, reverse=False) --> new sorted list"
);
"sorted(iterable, key=None, reverse=False) --> new sorted list"
);
static
PyObject
*
builtin_vars
(
PyObject
*
self
,
PyObject
*
args
)
...
...
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