Python3sort⾃定义⽐较函数
许多语⾔(例如C++/Java)的sort函数/⽅法都⽀持⾃定义⽐较类/函数,Python2的list的sort⽅法也⽀持可选参数cmp,⽀持⽤户⾃定义⽐较函数,但是Python3中删除了可选参数cmp,同时也删除了内置函数cmp,只提供了可选参数key⽤于⾃定义排序。但是,有些排序需求⽤cmp实现较为简单直接,不容易改写成key实现,为此,Python3的functools包提供了cmp_to_key函数,可以将⽤户⾃定义的cmp函数转化为可以被可选参数key接收的对象。
例如,在Python2中,以下实现
nums =[3,30,34,5,9]
nums.sort(cmp=lambda x,y:cmp(str(x)+str(y),str(y)+str(x)))
sort函数 js在Python3中,可以借⽤cmp_to_key转化为key参数的实现
from functools import cmp_to_key
nums =[3,30,34,5,9]
nums.sort(key=cmp_to_key(lambda x,y:int(str(x)+str(y))-int(str(y)+str(x))))
cmp_to_key的实现
cmp_to_key的源码如下,实际上就是定义了⼀个内部类K,通过传⼊的⽤户⾃定⽐较函数mycmp重写了K的各个⽐较⽅法:
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
关于__slots__
cmp_to_key源码中出现的__slots__魔法属性,⽤于规定⼀个类含有的属性和⽅法。由于Python的特性,实例化⼀个对象后,可以动态地给对象绑定属性和⽅法,例如给Person类的p对象添加属性age和⽅法hello:
from types import MethodType
def hello(self):
print('Hello! My name is {}'.format(self.name))
class Person:
def__init__(self, name):
super().__init__()
self.name = name
p = Person('da_kao_la')
p.age =10
print(p.age)# 10
p.hello = MethodType(hello, p)
p.hello()# Hello! My name is da_kao_la
如果使⽤了__slots__魔法属性规定了Person类只能含有属性name,则向Person类的对象动态添加属性和⽅法就会抛AttributeError异常。from types import MethodType
def hello(self):
print('Hello! My name is {}'.format(self.name))
class Person:
__slots__ =['name']
def__init__(self, name):
super().__init__()
self.name = name
p = Person('da_kao_la')
p.age =10
print(p.age)# AttributeError: 'Person' object has no attribute 'age'
p.hello = MethodType(hello, p)
p.hello()# AttributeError: 'Person' object has no attribute 'hello'
使⽤__slots__魔法属性在不需要动态添加属性和⽅法的时候可以减少内存使⽤,在实例化对象⾮常多的时候可以显著降低内存,因
此__slots__在库代码中时常可以见到,但是⼀般⽤户代码中不会同时创建那么多对象,因此不太会使⽤。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。