Python神器函数sorted():3个您不得不看的特性

开发 后端
在本文中,我们讨论了为什么几乎应该始终使用sorted()函数而不是sort()函数的三个原因。

作为一种通用语言,Python已在各种学术和工业领域逐渐流行,用于科学计算,工程,Web开发和许多其他用途。 Python的一项引人入胜的功能是它是如此灵活,以至于同一功能可以有多个实现。让我们考虑以下简单的示例。

  1. >>> # sort a list using sort() 
  2. >>> names0 = ['Danny', 'Johnny', 'Billy', 'Donny'] 
  3. >>> names0.sort() 
  4. >>> names0['Billy', 'Danny', 'Donny', 'Johnny'] 
  5. >>>>>> # sort a list using sorted() 
  6. >>> names1 = ['Danny', 'Johnny', 'Billy', 'Donny'] 
  7. >>> sorted(names1)['Billy', 'Danny', 'Donny', 'Johnny']>>> 

[“比利”,“丹尼”,“唐尼”,“约翰尼”]

在上面的代码中,我们创建了两个列表:names0和names1,并使用sort()和sorted()函数分别对它们进行排序。显然,我们能够以相同顺序在列表中获得。

尽管sort()和sorted()函数之间的相似之处,但我想指出,几乎总是要使用sorted()而不是sort()。这是三个原因。

1. 与任何迭代器的兼容性

第一个原因是sorted()函数更灵活,因为它可以与任何可迭代对象一起使用。相比之下,sort()函数仅适用于列表。如果您不知道什么是可迭代的,可以参考下面的我的上一篇文章。简而言之,可迭代对象是可以在迭代中进行迭代的Python对象,例如元组,列表,集合和字典。

让我们根据兼容的数据类型比较sorted()和sort()。需要注意的一件事是,这两种功能的使用方式存在细微的差异。 sorted()函数将iterable作为参数,而sort()函数的调用者则使用点表示法调用该函数。

  1. >>> # sort a tuple 
  2. >>> _ = (3, 5, 4).sort() 
  3. Traceback (most recent call last):  File "<stdin>", line 1, in <module> 
  4. AttributeError: 'tuple' object has no attribute 'sort' 
  5. >>> _ = sorted((3, 5, 4)) 
  6. >>>>>> # sort a dictionary>>> _ = {2: 'two', 0: 'zero', 1: 'one'}.sort()  
  7. Traceback (most recent call last):  File "<stdin>", line 1, in <module> 
  8. AttributeError: 'dict' object has no attribute 'sort' 
  9. >>> _ = sorted({2: 'two', 0: 'zero', 1: 'one'}) 
  10. >>>>>> # sort a set 
  11. >>> _ = set([2, 3, 4]).sort() 
  12. Traceback (most recent call last):  File "<stdin>", line 1, in <module> 
  13. AttributeError: 'set' object has no attribute 'sort' 
  14. >>> _ = sorted(set([2, 3, 4])) 

如上面的代码所示,元组,字典和集合均无法调用sort()函数。实际上,sort()函数是列表对象的实例方法,而不是其他集合对象的实例方法,这意味着此函数仅可用于列表对象。相比之下,元组,字典和集合都可以通过sorted()函数进行排序,因为所有这些数据类型都是可迭代的,因此使其适合使用sorted()函数。

2. 创建列表的便利

第二个原因是sorted()函数将按所需顺序对可迭代对象进行排序后将返回一个列表对象。因此,这是构建新列表的便捷方法。但是,sort()函数会更改调用此方法的列表的顺序,我们称此顺序为就地排序。此外,此函数隐式返回None(有时,我们可以说,当隐式返回值为None时,它不返回任何内容)。

让我们考虑以下假设示例。我们从一个名为sales_dict的字典开始,该字典保存全年的销售记录。我们要根据销售额创建一个按降序排列的记录列表。

  1. >>> # records of sales in a dictionary 
  2. >>> sales_dict = {'Spring': 1000, 'Summer': 950, 'Fall': 1030, 'Winter': 1200} 
  3. >>>>>> # create a list object of sales records 
  4. >>> sales_list0 = sorted(sales_dict.items(), key=lambda x: x[1], reverse=True
  5. >>> sales_list0[('Winter', 1200), ('Fall', 1030), ('Spring', 1000), ('Summer', 950)] 
  6. >>>>>> sales_list1 = list(sales_dict.items())>>> sales_list1.sort(key=lambda x: x[1], reverse=True
  7. >>> sales_list1[('Winter', 1200), ('Fall', 1030), ('Spring', 1000), ('Summer', 950)] 

在上面的代码中,我们只需要使用sorted()函数编写一行代码即可获得所需的结果。但是,使用sort()函数,我们必须编写两行代码。值得注意的是,由于某人可能会误认为,我们无法通过使用点符号来组合这两行来生成所需的列表对象。

  1. >>> # combine the two lines 
  2. >>> sales_list2 = list(sales_dict.items()).sort(key=lambda x: x[1], reverse=True
  3. >>> sales_list2>>> type(sales_list2) 
  4. <class 'NoneType'> 
  5. >>> print(sales_list2) 
  6. None 

如上面的代码所示,通过组合两行,我们得到的是None值。这是因为sort()函数的返回值为None,而不是调用该函数的列表对象。

3. 与迭代集成

由于sorted()函数返回列表,而sort()函数返回None,这种区别的含义是什么?好吧,在许多情况下,我们期望有可迭代对象,但没有NoneType对象。一种这样的场景是迭代,毕竟这是我们经常使用列表对象执行的一项关键操作。

考虑以下示例。我们有两个字典分别保存第一学期和第二学期的分数。目的是创建一个报告卡,总结每个学生的表现,并按姓名进行排序。

  1. >>> # test results for the first semester 
  2. >>> results1 = {'John': 95, 'Danny': 80, 'Zack': 98} 
  3. >>>>>> # test results for the second semester 
  4. >>> results2 = {'Danny': 84, 'Zack': 95, 'John': 88} 
  5. >>>>>> # generate the report card>>> for name, score in sorted(results2.items()): 
  6. ...     print(f'{name} | Spring: {results1[name]} | Fall: {score}') 
  7. ... Danny | Spring: 80 | Fall: 84 
  8. John | Spring: 95 | Fall: 88 
  9. Zack | Spring: 98 | Fall: 95 

在上面的代码中,我们注意到这两个字典都没有期望的输出顺序,因此,我们将使用sorted()函数对字典进行排序。如您所见,我们可以将排序后的结果直接集成到for循环中,因为sorted()函数返回排序后的列表。

您可能已经预料到,如果我们在这种情况下尝试使用sort()函数,将会发生什么。请参阅下面的更多细节。

  1. >>> for name, score in list(results2.items()).sort(): 
  2. ...     print(f'{name} | Spring: {results1[name]} | Fall: {score}') 
  3. ... Traceback (most recent call last):  File "<stdin>", line 1, in <module> 
  4. TypeError: 'NoneType' object is not iterable 

总结

在本文中,我们讨论了为什么几乎应该始终使用sorted()函数而不是sort()函数的三个原因。

  • sorted()函数更灵活,因为它可与任何可迭代对象一起使用,这与只适用于列表的sort()函数不同。
  • sorted()函数是创建排序列表的便捷方法。
  • sorted()函数可以方便地与迭代集成。

篇尾思考

最后但并非最不重要的一点是,您可能想知道何时应该考虑使用sort()函数。 对于这个问题,我没有确切的答案,但是我可以想到的一种情况是,当我们只处理列表对象而又不希望得到返回的列表时。 毕竟,sorted()函数将生成一个新列表,因此,当列表特别大时,使用sorted()函数创建新列表的内存使用效率不高。

考虑简单的例子。 我们需要对每个嵌套列表进行排序。 在某些情况下,列表可能非常大。 使用sort()函数只会对原始列表进行排序,从而避免创建不必要的新列表对象。

  1. >>> # simplified nested lists; each list can be much larger 
  2. >>> group_scores = [[7, 3, 5], [3, 2, 8], [9, 4, 5]] 
  3. >>> for scores in group_scores: 
  4. ...     scores.sort() 
  5. ... >>> group_scores[[3, 5, 7], [2, 3, 8], [4, 5, 9]] 

原文:

https://medium.com/swlh/3-reasons-why-you-should-almost-always-use-sorted-in-python-9fe122e6ce71

 

责任编辑:赵宁宁 来源: 今日头条
相关推荐

2014-10-30 13:38:55

编程算法程序员

2010-05-26 15:58:52

MySQL远程连接

2010-05-21 09:40:57

MySQL出错代码列表

2010-05-25 09:58:43

MySQL数据库

2010-05-10 13:01:03

OracleDBA面试

2010-06-13 11:21:32

MySQL 5.0

2010-07-23 18:39:52

SQL Server游

2019-12-10 15:30:27

SaaSIaaS云计算

2010-04-21 17:19:29

Oracle创建

2010-08-18 11:36:40

DB2简史

2010-05-18 10:34:29

MySQL数据库备份

2010-08-02 11:01:29

DB2 Resotre

2010-05-26 13:14:22

MySQL错误解决方案

2017-05-17 14:46:22

容器DockerLinux

2010-05-05 11:30:21

2010-09-28 09:42:16

2010-08-18 15:01:08

DB2 9安装方法

2018-01-24 09:52:18

SQL查询秘诀

2010-09-29 17:36:00

管理平台

2010-06-12 15:03:55

点赞
收藏

51CTO技术栈公众号