在 2.x 中,两种无法比较的内置类型的值按类型排序。类型的顺序没有定义,除非它在解释器的一次运行期间是一致的。所以,2 < [2]
可能是真或假,但它始终是真或假。
在 3.x 中,不可比较的内置类型的值是不可比较的——这意味着TypeError
如果您尝试比较它们,它们会引发 a。所以,2 < [2]
是一个错误。而且,至少从 3.3 开始,这些类型本身甚至没有可比性。但是,如果您只想重现 2.x 的行为,那么它们id
的 s 绝对是可比的,并且在解释器运行期间是一致的。所以:
sorted(items, key=lambda x: (id(type(x)), x))
对于您的用例,这就是您所需要的。
但是,这不会与 2.x 完全相同,因为这意味着,例如,1.5 < 2
可能是False
(因为float
> int
)。如果您想复制确切的行为,您需要编写一个键函数,首先尝试比较值,然后TypeError
回退到比较类型。
cmp
这是旧式函数比新式函数更容易阅读的少数情况之一key
,所以让我们编写其中一个,然后使用cmp_to_key
它:
def cmp2x(a, b):
try:
if a==b: return 0
elif a<b: return -1
elif b<a: return 1
except TypeError:
pass
return cmp2x(id(type(a)), id(type(b)))
sorted(items, key=functools.cmp_to_key(cmp2x))
这仍然不能保证 2.x 给出的不同类型的两个值之间的顺序相同,但是由于 2.x 没有定义任何这样的顺序(只是它在一次运行中是一致的),所以它不可能。
但是,仍然存在一个真正的缺陷:如果您定义的类的对象不是完全排序的,那么它们最终将排序为相等,我不确定这是否与 2.x 在这种情况下会做的事情相同。