如果你想相同的行为在这两个2.7早期版本的Python 2.x的(它使用了一个任意排列顺序,而不是)和3.x(其拒绝某种类型的字典),斯内德尔德的回答一个问题关于如何排序类型的字典工作得您是其中的一部分,但并非始终如此。
首先,它为您提供了旧式cmp
功能,而不是新式key
功能。幸运的是,2.7和3.x都functools.cmp_to_key
必须解决该问题。(您当然可以将代码重写为一个关键函数,但这可能会使查看所发布的代码与您的代码之间的任何区别变得更加困难……)
更重要的是,它不仅在2.7和3.x中没有做同样的事情,甚至在2.7和3.x中也 不起作用 。要了解原因,请查看代码:
def smallest_diff_key(A, B):
"""return the smallest key adiff in A such that A[adiff] != B[bdiff]"""
diff_keys = [k for k in A if A.get(k) != B.get(k)]
return min(diff_keys)
def dict_cmp(A, B):
if len(A) != len(B):
return cmp(len(A), len(B))
adiff = smallest_diff_key(A, B)
bdiff = smallest_diff_key(B, A)
if adiff != bdiff:
return cmp(adiff, bdiff)
return cmp(A[adiff], b[bdiff])
请注意,它正在调用cmp
不匹配的值。
如果这些命令可以包含其他命令,则取决于cmp(d1, d2)
最终将调用此函数的事实……这在较新的Python中显然不是正确的。
最重要的是,在3.xcmp
中甚至不存在。
另外,这还取决于任何值都可以与任何其他值进行比较的事实- 您可以返回任意结果,但不会出现异常。在2.x中确实如此(在少数情况下除外),但在3.x中则并非如此。如果您不希望将字典与不可比较的值进行比较(例如,如果可以{1: 2} < {1: 'b'}
引发异常),那对您来说可能不是问题,但是相反。
当然,如果您不希望将任意结果用于dict比较,您是否真的想要任意结果用于值比较?
解决这三个问题的方法很简单:您必须替换cmp
,而不是调用它。因此,如下所示:
def mycmp(A, B):
if isinstance(A, dict) and isinstance(B, dict):
return dict_cmp(A, B)
try:
return A < B
except TypeError:
# what goes here depends on how far you want to go for consistency
如果您想要2.7所使用的用于比较不同类型对象的确切规则,则将其记录在案,以便您可以实现它们。但是,如果您不需要那么多细节,则可以在此处编写更简单的内容(TypeError
如果可以接受上述异常,甚至可以不捕获)。