sorted函数有三个参数:iterable、key、reverse。
其中,iterable为一个可迭代的对象,reverse表示是否对排序结果进行反转,而key稍微复杂一点,主要是用来对需要比较的元素进行处理,可以是一个函数,也可以是一个类,也可以是其他的处理方法。
key的工作原理
key的大概工作流程就是首先对序列中所有的元素逐一调用方法、函数或者类进行处理,如果是方法,一般是返回一个固定的值这个值一般是内置的类型。如果是类,则是直接调用构造函数,生成一个对象,所以作为key的类必须有一个构造函数,这个函数仅支持一个参数(除self外)用来接收序列中的元素。
内建函数\方法
先来看使用内建的函数或者方法处理的效果:
ls = ["a", "b", "c", "D", "E"] # 直接排序,结果为['D', 'E', 'a', 'b', 'c'] print(sorted(ls)) # 使用lower,将所有元素转化为小写字母再排序['a', 'b', 'c', 'D', 'E'] # 因为lower是字符串的方法,所以这里要加上调用方为字符串类型 print(sorted(ls, key=str.lower))
自定义函数
既然可以使用内建的函数或者方法,那么当然也可以自定义函数,执行排序时,会对序列中的每一个元素依次调用我们指定的函数,然后把返回值拿来做比较。
# 例如我们想把列表中的数字按照个位的大小进行排序,那么就可以定义一个函数,返回一个整数的个位数 def gewei(num: int) -> int: return num % 10 ls = [991, 86, 3] # 结果为[991, 3, 86] print(sorted(ls, key=gewei)) # 当然,我们也可以写lamda表达式(匿名函数),结果是一样的 print(sorted(ls, key=lambda num: num % 10))
类
前面说到了,如果传入类作为key的参数,那么会依次将序列中的元素作为类构造函数的参数,然后将生成的对象作比较。
这里要提一点,对象作比较,实际上是调用类的__lt__或者__gt__方法,因此,类必须实现其中一个方法。
关于__lt__和__gt__方法
__lt__、__gt__分别表示:小于、大于,对应的操作符为:'<'、'>'。
1.当自定义类中两个方法都定义了时,'<'和'>'分别调用__lt__和__gt__方法;
2.当自定义类中定义了__lt__方法,未定义__gt__方法时,进行”>”比较也是调用__lt__方法,只是对调用值求反。
class Stu: def __init__(self, name, age): self.name = name self.age = age # __lt__方法有两个参数,分别表示自身对象和其它对象,这种格式是固定的,__gt__也是一样 # 这里我们定义,两个Stu对象比较时,age属性较小的一方更小 def __lt__(self, other): return self.age < other.age s1 = Stu("小明", 10) s2 = Stu("小红", 12) # 结果为True,如果类里没有实现__lt__或者__gt__方法,那这里就会报错
print(s1 < s2)
类作为key参数
上面定义的类构造函数需要接受两个参数,name和age,所以这样的类是不能作为key的参数值的,因为key是将序列中的每一个元素依次传入,所以类构造函数能且只能接受一个参数:
class Stu: def __init__(self, age): self.age = age def __lt__(self, other): # 这里我故意反着来,年龄比较大的一方反而更小 return self.age > other.age ls = [10, 20, 11, 4, 9, 23] # 虽然默认为升序,但是比较规则里是年龄更大的对象更小,所以年龄大的会排前面 # 结果为[23, 20, 11, 10, 9, 4] print(sorted(ls, key=Stu))
标签:__,函数,age,lt,ls,key,sorted,self From: https://www.cnblogs.com/haruyuki/p/16758134.html