python 的 functools.cmp_to_key 返回什么?

gup*_*ark 5 python functools

我在文档中得到了这一点,我可以使用 cmp_to_key 将旧式比较从 python2 转换为关键函数,例如在 python3 中,但我不知道返回的究竟是什么。例如:

def my_cmp(a, b):
    if(a == b):
        return 0
    elif(a < b):
        return -1
    else:
        return 1

my_key_fn = functools.cmp_to_key(my_cmp)
Run Code Online (Sandbox Code Playgroud)

然后每当我对任何数字调用 my_key_fn 时,结果是一个新函数的地址,每次调用都有一个新地址。例如:

In [49]: my_key_fn(1)
Out[49]: <functools.KeyWrapper at address...>
Run Code Online (Sandbox Code Playgroud)

我认为返回值会给我某种可以用作排序键的值。为什么我会得到一个函数包装器?

wim*_*wim 0

中提供了一个纯 Python 实现functools.py,复制如下:

def cmp_to_key(mycmp):
    """Convert a cmp= function into a key= function"""
    class K(object):
        __slots__ = ['obj']
        def __init__(self, obj):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        __hash__ = None
    return K
Run Code Online (Sandbox Code Playgroud)

您所看到的返回实例functools.KeyWrapper实际上并非来自此 Python 代码,而是您可以在 中找到的 C 实现_functoolsmodule.c。技术是相似的:它不需要返回某种标量值,例如整数,它只需要返回可以相互比较的东西。它只需定义必要的比较运算符(使用cmp调用者提供的函数)即可实现这一点。

我认为返回值会给我某种可以用作排序键的值。为什么我会得到一个函数包装器?

它不是一个可以用作排序键的值,它排序键。

反转整数或字符串的正常顺序,例如:

def cmp_to_key(mycmp):
    class K:
        def __init__(self, obj):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
    return K

def cmp(x, y):
    return 1 if x < y else 0 if x == y else -1

key = cmp_to_key(cmp)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> "foo" < "bar"
False
>>> key("foo") < key("bar")
True
>>> sorted([1,2,3], key=key)
[3, 2, 1]
Run Code Online (Sandbox Code Playgroud)