Python 为什么这个用于排序异构序列的关键类行为异常?

Python 为什么这个用于排序异构序列的关键类行为异常?,python,python-3.x,sorting,python-2.x,complex-numbers,Python,Python 3.x,Sorting,Python 2.x,Complex Numbers,Python3.x的函数不能用于对异构序列进行排序,因为大多数不同类型的对都是无序的(数值类型,如int,float,decimal.decimal等,属于例外): 为了在Python3.x中复制Python2.x的行为,我编写了一个类作为键参数用于sorted(),这取决于sorted()仅使用少于比较的事实: class motley: def __init__(self, value): self.value = value def __lt__(sel

Python3.x的函数不能用于对异构序列进行排序,因为大多数不同类型的对都是无序的(数值类型,如
int
float
decimal.decimal
等,属于例外):

为了在Python3.x中复制Python2.x的行为,我编写了一个类作为
参数用于
sorted()
,这取决于
sorted()
仅使用少于比较的事实:

class motley:

    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        try:
            return self.value < other.value
        except TypeError:
            return repr(type(self.value)) < repr(type(other.value))
到目前为止,一切顺利

然而,我注意到当使用包含复数的特定序列调用
排序(s,key=motley)
时,出现了一种令人惊讶的行为:

>>> sorted([0.0, 1, (1+0j), False, (2+3j)], key=motley)
[(1+0j), 0.0, False, (2+3j), 1]
我希望
0.0
False
1
在一组中(因为它们可以相互排序),而
(1+0j)
(2+3j)
在另一组中(因为它们属于同一类型)。这个结果中的复数不仅彼此分离,而且其中的一个坐在一组彼此比较但不与之相伴的对象的中间,这有点令人困惑。
这里发生了什么?

您不知道比较是按什么顺序进行的,甚至不知道比较了哪些项目,这意味着您无法真正知道您的
\ult\uu
将产生什么影响。您定义的
\uu lt\uuu
有时取决于实际值,有时取决于类型的字符串表示形式,但在排序过程中,两个版本可能用于同一对象。这意味着您的顺序不仅由列表中的对象决定,还可能取决于它们的初始顺序。这反过来意味着,仅仅因为对象是相互可比的,并不意味着它们将被分类在一起;它们可能被它们之间不可比较的对象“阻挡”

您可以通过放入一些调试打印来了解正在进行的操作,以查看其比较结果:

class motley:

    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        fallback = False
        try:
            result = self.value < other.value
        except TypeError:
            fallback = True
            result = repr(type(self.value)) < repr(type(other.value))
        symbol = "<" if result else ">"
        print(self.value, symbol, other.value, end="")
        if fallback:
            print(" -- because", repr(type(self.value)), symbol, repr(type(other.value)))
        else:
            print()
        return result

(因为
'float'
:-)

我不确定,但您所描述的也可能是Python排序算法应该是稳定的,因为它不会对已经排序的序列重新排序。看,嘿。。。是的,
a
循环确实扼杀了整个方法,不是吗?谢谢你的详细回答:-)我想你可能有兴趣知道我已经发布了一个。。。
>>> sorted(["one", 2.3, "four", -5], key=motley)
[-5, 2.3, 'four', 'one']
>>> sorted([0.0, 1, (1+0j), False, (2+3j)], key=motley)
[(1+0j), 0.0, False, (2+3j), 1]
class motley:

    def __init__(self, value):
        self.value = value

    def __lt__(self, other):
        fallback = False
        try:
            result = self.value < other.value
        except TypeError:
            fallback = True
            result = repr(type(self.value)) < repr(type(other.value))
        symbol = "<" if result else ">"
        print(self.value, symbol, other.value, end="")
        if fallback:
            print(" -- because", repr(type(self.value)), symbol, repr(type(other.value)))
        else:
            print()
        return result
>>> sorted([0.0, 1, (1+0j), False, (2+3j)], key=motley)
1 > 0.0
(1+0j) < 1 -- because <class 'complex'> < <class 'int'>
(1+0j) < 1 -- because <class 'complex'> < <class 'int'>
(1+0j) < 0.0 -- because <class 'complex'> < <class 'float'>
False > 0.0
False < 1
(2+3j) > False -- because <class 'complex'> > <class 'bool'>
(2+3j) < 1 -- because <class 'complex'> < <class 'int'>
[(1+0j), 0.0, False, (2+3j), 1]
>>> motley(1.0) < motley(lambda: 1) < motley(0) < motley(1.0)
True