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
0603d304
Kaydet (Commit)
0603d304
authored
Ock 06, 2015
tarafından
Raymond Hettinger
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #23132: Mitigate regression in speed and clarity in functools.total_ordering.
üst
212994e4
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
80 additions
and
64 deletions
+80
-64
functools.py
Lib/functools.py
+78
-64
NEWS
Misc/NEWS
+2
-0
No files found.
Lib/functools.py
Dosyayı görüntüle @
0603d304
...
...
@@ -89,91 +89,106 @@ def wraps(wrapped,
### total_ordering class decorator
################################################################################
# The correct way to indicate that a comparison operation doesn't
# recognise the other type is to return NotImplemented and let the
# interpreter handle raising TypeError if both operands return
# NotImplemented from their respective comparison methods
#
# This makes the implementation of total_ordering more complicated, since
# we need to be careful not to trigger infinite recursion when two
# different types that both use this decorator encounter each other.
#
# For example, if a type implements __lt__, it's natural to define
# __gt__ as something like:
#
# lambda self, other: not self < other and not self == other
#
# However, using the operator syntax like that ends up invoking the full
# type checking machinery again and means we can end up bouncing back and
# forth between the two operands until we run out of stack space.
#
# The solution is to define helper functions that invoke the appropriate
# magic methods directly, ensuring we only try each operand once, and
# return NotImplemented immediately if it is returned from the
# underlying user provided method. Using this scheme, the __gt__ derived
# from a user provided __lt__ becomes:
#
# lambda self, other: _not_op_and_not_eq(self.__lt__, self, other))
def
_not_op
(
op
,
other
):
# "not a < b" handles "a >= b"
# "not a <= b" handles "a > b"
# "not a >= b" handles "a < b"
# "not a > b" handles "a <= b"
op_result
=
op
(
other
)
# The total ordering functions all invoke the root magic method directly
# rather than using the corresponding operator. This avoids possible
# infinite recursion that could occur when the operator dispatch logic
# detects a NotImplemented result and then calls a reflected method.
def
_gt_from_lt
(
self
,
other
):
'Return a > b. Computed by @total_ordering from (not a < b) and (a != b).'
op_result
=
self
.
__lt__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
and
self
!=
other
def
_le_from_lt
(
self
,
other
):
'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).'
op_result
=
self
.
__lt__
(
other
)
return
op_result
or
self
==
other
def
_ge_from_lt
(
self
,
other
):
'Return a >= b. Computed by @total_ordering from (not a < b).'
op_result
=
self
.
__lt__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
def
_op_or_eq
(
op
,
self
,
other
):
# "a < b or a == b" handles "a <= b"
# "a > b or a == b" handles "a >= b"
op_result
=
op
(
other
)
def
_ge_from_le
(
self
,
other
):
'Return a >= b. Computed by @total_ordering from (not a <= b) or (a == b).'
op_result
=
self
.
__le__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
op_result
or
self
==
other
return
not
op_result
or
self
==
other
def
_lt_from_le
(
self
,
other
):
'Return a < b. Computed by @total_ordering from (a <= b) and (a != b).'
op_result
=
self
.
__le__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
op_result
and
self
!=
other
def
_gt_from_le
(
self
,
other
):
'Return a > b. Computed by @total_ordering from (not a <= b).'
op_result
=
self
.
__le__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
def
_not_op_and_not_eq
(
op
,
self
,
other
):
# "not (a < b or a == b)" handles "a > b"
# "not a < b and a != b" is equivalent
# "not (a > b or a == b)" handles "a < b"
# "not a > b and a != b" is equivalent
op_result
=
op
(
other
)
def
_lt_from_gt
(
self
,
other
):
'Return a < b. Computed by @total_ordering from (not a > b) and (a != b).'
op_result
=
self
.
__gt__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
and
self
!=
other
def
_not_op_or_eq
(
op
,
self
,
other
):
# "not a <= b or a == b" handles "a >= b"
# "not a >= b or a == b" handles "a <= b"
op_result
=
op
(
other
)
def
_ge_from_gt
(
self
,
other
):
'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).'
op_result
=
self
.
__gt__
(
other
)
return
op_result
or
self
==
other
def
_le_from_gt
(
self
,
other
):
'Return a <= b. Computed by @total_ordering from (not a > b).'
op_result
=
self
.
__gt__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
def
_le_from_ge
(
self
,
other
):
'Return a <= b. Computed by @total_ordering from (not a >= b) or (a == b).'
op_result
=
self
.
__ge__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
or
self
==
other
def
_op_and_not_eq
(
op
,
self
,
other
):
# "a <= b and not a == b" handles "a < b"
# "a >= b and not a == b" handles "a > b"
op_result
=
op
(
other
)
def
_gt_from_ge
(
self
,
other
):
'Return a > b. Computed by @total_ordering from (a >= b) and (a != b).'
op_result
=
self
.
__ge__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
op_result
and
self
!=
other
def
_lt_from_ge
(
self
,
other
):
'Return a < b. Computed by @total_ordering from (not a >= b).'
op_result
=
self
.
__ge__
(
other
)
if
op_result
is
NotImplemented
:
return
NotImplemented
return
not
op_result
def
total_ordering
(
cls
):
"""Class decorator that fills in missing ordering methods"""
convert
=
{
'__lt__'
:
[(
'__gt__'
,
lambda
self
,
other
:
_not_op_and_not_eq
(
self
.
__lt__
,
self
,
other
)
),
(
'__le__'
,
lambda
self
,
other
:
_op_or_eq
(
self
.
__lt__
,
self
,
other
)
),
(
'__ge__'
,
lambda
self
,
other
:
_not_op
(
self
.
__lt__
,
other
)
)],
'__le__'
:
[(
'__ge__'
,
lambda
self
,
other
:
_not_op_or_eq
(
self
.
__le__
,
self
,
other
)
),
(
'__lt__'
,
lambda
self
,
other
:
_op_and_not_eq
(
self
.
__le__
,
self
,
other
)
),
(
'__gt__'
,
lambda
self
,
other
:
_not_op
(
self
.
__le__
,
other
)
)],
'__gt__'
:
[(
'__lt__'
,
lambda
self
,
other
:
_not_op_and_not_eq
(
self
.
__gt__
,
self
,
other
)
),
(
'__ge__'
,
lambda
self
,
other
:
_op_or_eq
(
self
.
__gt__
,
self
,
other
)
),
(
'__le__'
,
lambda
self
,
other
:
_not_op
(
self
.
__gt__
,
other
)
)],
'__ge__'
:
[(
'__le__'
,
lambda
self
,
other
:
_not_op_or_eq
(
self
.
__ge__
,
self
,
other
)
),
(
'__gt__'
,
lambda
self
,
other
:
_op_and_not_eq
(
self
.
__ge__
,
self
,
other
)
),
(
'__lt__'
,
lambda
self
,
other
:
_not_op
(
self
.
__ge__
,
other
)
)]
'__lt__'
:
[(
'__gt__'
,
_gt_from_lt
),
(
'__le__'
,
_le_from_lt
),
(
'__ge__'
,
_ge_from_lt
)],
'__le__'
:
[(
'__ge__'
,
_ge_from_le
),
(
'__lt__'
,
_lt_from_le
),
(
'__gt__'
,
_gt_from_le
)],
'__gt__'
:
[(
'__lt__'
,
_lt_from_gt
),
(
'__ge__'
,
_ge_from_gt
),
(
'__le__'
,
_le_from_gt
)],
'__ge__'
:
[(
'__le__'
,
_le_from_ge
),
(
'__gt__'
,
_gt_from_ge
),
(
'__lt__'
,
_lt_from_ge
)]
}
# Find user-defined comparisons (not those inherited from object).
roots
=
[
op
for
op
in
convert
if
getattr
(
cls
,
op
,
None
)
is
not
getattr
(
object
,
op
,
None
)]
...
...
@@ -183,7 +198,6 @@ def total_ordering(cls):
for
opname
,
opfunc
in
convert
[
root
]:
if
opname
not
in
roots
:
opfunc
.
__name__
=
opname
opfunc
.
__doc__
=
getattr
(
int
,
opname
)
.
__doc__
setattr
(
cls
,
opname
,
opfunc
)
return
cls
...
...
Misc/NEWS
Dosyayı görüntüle @
0603d304
...
...
@@ -47,6 +47,8 @@ Library
- Issue #23111: In the ftplib, make ssl.PROTOCOL_SSLv23 the default protocol
version.
- Issue #23132: Mitigate regression in speed and clarity in functools.total_ordering.
- Issue #22585: On OpenBSD 5.6 and newer, os.urandom() now calls getentropy(),
instead of reading /dev/urandom, to get pseudo-random bytes.
...
...
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