浅谈python语言中的sort()方法和sorted()函数

为什么要写这篇博客?

【美】Eric Matthes著 袁国忠译的《Python编程从入门到实践》是许多Python初学者的必备读物,这篇工具书整体的结构紧凑,由浅入深,很适合新手入门使用。在原书中第三章 列表简介 3.3组织列表一节中,分别有以下两小节标题:

  • 3.3.1 使用方法 sort()对列表进行永久性排序
  • 3.3.2 使用函数 sorted()对列表进行临时排序

看到此处我想有相当一部分同学已经懵逼了,明明形式看着是一样的,怎么一个成了方法,一个成了函数?难道是因为一个能够实现永久排序,一个只是将排序结果输出不改变原有次序?

对于没有任何变成基础的小白,这几个问题可以说是致命的,但我尝试在baidu上搜索“方法和函数”时,搜索排第一的是行业同仁的这篇文章:方法和函数区别,可惜阅读量只有1200,下意识让我觉得还需要读别的文章寻找答案。(在校学生,转业工人们在网络查阅非官方资料时,都应该有注意访问量的意识!)第二条搜索结果函数和方法的区别就有点多了,接近7w的阅读量,收藏量也有130+,还是转载文,虽然没来源,如此看,这个是很靠谱了。可能是从某官文扒来的。再看看评论区,果然天下苦“方法函数”久矣。其中一句话应该会被不少人奉为圭臬,“方法也是函数,只是比较特殊的函数”,此话一出杀伤力之强,令人咋舌。首先我必须要在此补充,直接引用,这里给出出处。python.org文档

The other kind of instance attribute reference is a method. A method is a function that “belongs to” an object. (In Python, the term method is not unique to class instances: other object types can have methods as well. For example, list objects have methods called append, insert, remove, sort, and so on. However, in the following discussion, we’ll use the term method exclusively to mean methods of class instance objects, unless explicitly stated otherwise.)

一言以蔽之,方法可以是函数,但在一定的前提条件下,才可以这么认为。

唉,跑题了,今天我想解决的只是标题中的问题,希望以下的回答能有所帮助。

勘误:书中目录的sort()写全应为list.sort()

这样写就可以让10%有疑惑的人恍然大悟!

列表list(之后叙述皆使用list),作为Python语言其中的一个内置类,作为Python中最基本的几类数据结构之一,list类可看作是序列sequence类的一种。

(在python语言中用一个巧妙的办法,将list类变为了sequence类的虚拟子类)

而sequence类在Python源代码中写在collections.abc.Sequence的部分,这是abc标准库的内容,到此为止,这才算刨到了根上。

上面这一小段斜体内容你不需要吃透,我想传达的,这里的关键信息其实只有一个,即list本身是类的一种,list实现了所有一般和可变序列的操作。 而list提供了一个方法,就是sort()。

sorted()函数可以接受任何的可迭代对象!

是的,因为原书在讲列表时分别列举了一个方法和一个函数,他们都被应用在了list上,所以给学习的人造成了困扰。直接上一个可行的例子:

>>> sorted([5, 2, 3, 1, 4]) # list
[1, 2, 3, 4, 5]
>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'}) # dict
[1, 2, 3, 4, 5]

是的,字典类型也适用。诸如此类的,所有的可迭代对象都可以使用 sorted() !

list.sort()是python内置list类下的一个方法,它会直接修改原列表,(并返回None以避免混淆)。sorted()是python内置函数,它会从一个可迭代对象构建一个新的排序列表,返回的也是这个新的排序列表。

仅在list的排序两者才能共同使用,有效率的比较价值。从效率上讲,虽然二者的底层逻辑都使用传奇的timsort排序法,但深究排序速度,sort()和sorted()相比会略快一些,理解的话,你可以理解为:sort()方法为list专精开发,sorted()因为具有普适性,所以会略慢一些 (如果sorted()全面碾压,那还要sort()方法做什么呢?)

提供给好奇宝宝们一个自己动手的机会

#--------part-1-分别生成含重复项和不含重复项的list------------
import random    # python2.7起和python3出生自带的包
import copy

bordernum = 10000 # 设置生成数字的边界,这个值别搞太大,小心把电脑跑死了,我测试最大用了100万
list1 = []
for _ in range(bordernum):
	list1.append(random.randint(0,bordernum))	# 在list1中填充100个[0,100]的随机整数,列表元素可能重复
list2 = copy.deepcopy(list1)	# deepcopy是为了复制一份一模一样的list1,且对list1排序时不影响list2,对于deepcopy()深复制的知识点,本文不做探讨
list3 = []
for i in range(bordernum):
	list3.append(i)	# 在list2中逐次填充0~99的整数,列表元素不重复
random.shuffle(list3) # random.shuffle()作用是将一个序列中各元素顺序随机打乱,并将打乱后的结果返回给原始序列
list4 = copy.deepcopy(list3)

#--------part-2.1-测试sort()和sorted()的耗时差距-----------
import time
start = time.time()
list1.sort()
end = time.time()
print("执行完毕,共耗时", end - start)

start = time.time()
sorted(list2)
end = time.time()
print("执行完毕,共耗时", end - start)

#--------part-2.2-测试sort()和sorted()的耗时差距-----------
import time
start = time.time()
list3.sort()
end = time.time()
print("执行完毕,共耗时", end - start)

start = time.time()
sorted(list4)
end = time.time()
print("执行完毕,共耗时", end - start)
延伸一下

排序作为各类序列中使用最频繁的操作之一,它赋予了一个乱序序列探寻挖掘更多价值的可能。抛弃各类编程语言,就以学习办公中最常使用的office三大将的数据处理利器Excel来说,对于表格操作,其最重要的两大类功能就是筛选和排序。且基于两类操作,向下又延申了更为复杂的高级筛选和排序操作。编程语言以其高度的自由和可操作性,给了分析师更多的想象空间,挖掘数据价值的潜力变得更大。
而让排序变得更加自由的关键,其实就在上述sort()和sorted()的两个重要形式参数里,即key和reverse
。其中的key形参更是能玩出花来。它本身有如下的定义:

key 指定带有一个参数的函数,用于从每个列表元素中提取比较键 (例如 key=str.lower)。 对应于列表中每一项的键会被计算一次,然后在整个排序过程中使用。 默认值 None 表示直接对列表项排序而不计算一个单独的键值

根据我浅薄的经验,key可以传入以下几类内容:

  1. lambda 自定义表达式
  2. 函数(含自定义函数表达式)
  3. 类方法
  4. 在类中直接定义
# ------1.lambda表达式------
list5
# ------2.函数 ------
list6 = 
# ------3.类方法------
list7 = ['China','THE USA','Berlin','beijing','TsingTao','Hongkong']
list7.sort()

通过上面几个例子,可以看到key的作用是在简化list到排序前的倒数第二步,简化完毕后,根据对应规则进行排序。对list进行大小写无差别的排序,就先把序列的大小写特征去除;对list中嵌套的list指定按照第1个元素排序,就先将原序列精简到仅包含第1个元素再排序…可以说,key给定的各种约束规则,让序列仅对制定好的规则下产生的序列做排序,并将对应的序号让原有的元素放在对应的位置上。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值