mat*_*sco 28 python sorting deprecated
在Python中,list.sort方法和sorted内置函数都接受一个名为的可选参数key,该参数是一个函数,给定列表中的元素返回其排序键.
较旧的Python版本使用了一个不同的方法,cmp而不是使用参数,这是一个函数,给定列表中的两个元素,如果第一个小于第二个,则返回负数,如果有等于则返回零,如果第一个是,则返回正数更大.在某些时候,此参数已弃用,并未包含在Python 3中.
有一天,我想以一种cmp函数比一个函数更容易编写的方式对元素列表进行排序key.我并不想这样我阅读文档,我发现有一个名为funtion使用弃用的功能cmp_to_key中functools,正如他的名字状态,接收模块cmp功能,并返回key一个......或者这就是我想直到我阅读了文档中包含的这个高级函数的源代码(或至少是等效版本)
def cmp_to_key(mycmp):
'Convert a cmp= function into a key= function'
class K(object):
def __init__(self, obj, *args):
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
def __ne__(self, other):
return mycmp(self.obj, other.obj) != 0
return K
Run Code Online (Sandbox Code Playgroud)
尽管事实上cmp_to_key按预期工作,但我感到惊讶的是,这个函数不会返回函数而是返回K类.为什么?它是如何工作的?我猜这个sorted函数在内部检查cmp是函数还是K类或类似东西,但我不确定.
PS:尽管他很奇怪,但我发现K级非常有用.检查此代码:
from functools import cmp_to_key
def my_cmp(a, b):
# some sorting comparison which is hard to express using a key function
class MyClass(cmp_to_key(my_cmp)):
...
Run Code Online (Sandbox Code Playgroud)
这样,默认情况下,MyClass的任何实例列表都可以按照中定义的条件进行排序 my_cmp
Ana*_*mar 26
不,sorted函数(或list.sort)内部不需要检查它收到的对象是函数还是类.它所关心的只是它在key参数中接收的对象应该是可调用的,并且应该返回一个值,该值可以在调用时与其他值进行比较.
类也可以调用,当你调用一个类时,你会收到该类的实例.
要回答你的问题,首先我们需要理解(至少在基本层面)key参数是如何工作的 -
该key调用被调用用于每个元素,并将其接收回与它应该排序的对象.
在接收到新对象后,它将其与其他对象进行比较(再次通过key使用其他元素调用callable来接收).
现在需要注意的重要一点是,将新object收到的内容与其他相同的对象进行比较.
现在进入等效代码,当您创建该类的实例时,可以使用您的mycmp函数将其与同一类的其他实例进行比较.排序时排序值会比较这些对象(实际上)调用您的mycmp()函数以确定该值是否小于或大于另一个对象.
打印语句示例 -
>>> def cmp_to_key(mycmp):
... 'Convert a cmp= function into a key= function'
... class K(object):
... def __init__(self, obj, *args):
... print('obj created with ',obj)
... self.obj = obj
... def __lt__(self, other):
... print('comparing less than ',self.obj)
... return mycmp(self.obj, other.obj) < 0
... def __gt__(self, other):
... print('comparing greter than ',self.obj)
... return mycmp(self.obj, other.obj) > 0
... def __eq__(self, other):
... print('comparing equal to ',self.obj)
... return mycmp(self.obj, other.obj) == 0
... def __le__(self, other):
... print('comparing less than equal ',self.obj)
... return mycmp(self.obj, other.obj) <= 0
... def __ge__(self, other):
... print('comparing greater than equal',self.obj)
... return mycmp(self.obj, other.obj) >= 0
... def __ne__(self, other):
... print('comparing not equal ',self.obj)
... return mycmp(self.obj, other.obj) != 0
... return K
...
>>> def mycmp(a, b):
... print("In Mycmp for", a, ' ', b)
... if a < b:
... return -1
... elif a > b:
... return 1
... return 0
...
>>> print(sorted([3,4,2,5],key=cmp_to_key(mycmp)))
obj created with 3
obj created with 4
obj created with 2
obj created with 5
comparing less than 4
In Mycmp for 4 3
comparing less than 2
In Mycmp for 2 4
comparing less than 2
In Mycmp for 2 4
comparing less than 2
In Mycmp for 2 3
comparing less than 5
In Mycmp for 5 3
comparing less than 5
In Mycmp for 5 4
[2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)
我刚刚意识到,尽管 K 类不是一个函数,但它是一个可调用的,因为它是一个类!类是可调用的,当被调用时,会创建一个新实例,通过调用相应的实例来初始化它__init__,然后返回该实例。
这样,它的行为就像一个key函数,因为 K 在调用时接收该对象,并将该对象包装在 K 实例中,该实例可以与其他 K 实例进行比较。
如我错了请纠正我。我觉得我正在进入我不熟悉的元类领域。
| 归档时间: |
|
| 查看次数: |
10035 次 |
| 最近记录: |