文章目录
- 一、工具
- 二、需求
- 三、简单的使用例子
- 四、原理分析
- Timsort算法主要特点:
- Timsort算法的工作原理:
- `sort()` 方法和 `sorted()` 函数的差异:
- 五、Python中的单例实现简单示例
一、工具
Python 3.10.0
pycharm 2022
二、需求
最近做项目的时候用到了这两个函数,以前没注意,仔细研究一下,这两个函数还是有很大区别的
三、简单的使用例子
在Python中,你可以使用内置的sort()方法或者sorted()函数对列表进行排序。
- sort() 方法 - 会修改原始列表,使其元素按照一定顺序排列。默认情况下,排序是升序的。
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
my_list.sort()
print(my_list) # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
如果你要按照降序排序,可以传递一个参数reverse=True
给sort()
方法:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
my_list.sort(reverse=True)
print(my_list) # 输出: [9, 6, 5, 4, 3, 2, 1, 1]
你还可以提供一个自定义的关键字参数key来实现自定义排序逻辑:
my_list = ['apple', 'banana', 'cherry', 'date']
my_list.sort(key=len) # 根据字符串长度排序
print(my_list) # 输出: ['date', 'apple', 'banana', 'cherry']
- sorted() 函数 - 会返回一个新的列表,并且不会改变原始的列表。用法和sort()类似,但是它可以用于任何可迭代对象:
my_list = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_list = sorted(my_list)
print(sorted_list) # 输出: [1, 1, 2, 3, 4, 5, 6, 9]
同样地,你也可以使用reverse
和key
参数:
my_list = ['apple', 'banana', 'cherry', 'date']
sorted_list = sorted(my_list, key=len, reverse=True)
print(sorted_list) # 输出: ['banana', 'cherry', 'apple', 'date']
这里的len是Python内置函数,用来获取列表中每个元素的长度作为排序的依据(即排序键)。sort()和sorted()都支持自定义的函数
作为key
参数,这允许你进行更复杂的排序操作。
选择sort()方法还是sorted()函数取决于是否需要保留原始列表不变
,以及是否需要对任意可迭代对象进行排序
。
四、原理分析
在Python中,sort()方法和sorted()函数背后的排序机制是基于Tim Peters开发的Timsort算法。Timsort是一种混合型排序算法,它源自归并排序(Merge Sort)和插入排序(Insertion Sort)。Timsort算法在2002年被引入到Python中,并且因为其卓越性能成为Python的默认排序算法。
Timsort算法主要特点:
- 稳定性:如果列表中存在相等的元素,它们原始的顺序不会改变。
- 自适应性:在接近排好序的数据集上表现更佳。
- 复杂度: 最坏情况时间复杂度为O(n log n)。 最优情况(已经排好序的数据集)时间复杂度为O(n)。 平均情况时间复杂度也是O(n log n)。
Timsort算法的工作原理:
-
查找或创建自然运行:Timsort首先遍历数据,查找自然有序的小段,称为“运行”(runs),这些可以是已经排好序的子列表。如果没有找到足够大小的运行,则使用二分插入排序将它们扩展到最小运行大小(通常为32或64个元素)。这一步骤允许算法利用输入数据中的任何固有顺序。
-
运行堆积(Run Stacking):一旦识别出所有的运行之后,Timsort会按照一定规则将它们合并,直到只剩下一个运行为止。这个过程中,Timsort会尽可能地合并那些长度相近的相邻运行。
-
归并排序:合并过程是通过归并排序完成的,这是一种将两个或多个有序列表组合成单一有序列表的技术。通过重复此过程,直到整个数组变得有序。
sort()
方法和 sorted()
函数的差异:
- sort() 方法:
是列表(list)的内置方法。
会就地(in-place)对列表进行排序,即不需要额外的存储空间来创建新列表,但原始列表内容会被改变。
2. sorted() 函数:
是内建函数,可以对任意可迭代对象进行排序操作。
返回一个新的列表,原始输入数据不会被修改。
尽管sort()和sorted()使用相同的排序算法(Timsort),它们在数据处理方式上存在差异,体现在是否会改变原始数据以及它们各自的适用范围。
在高级实现中,Timsort还涉及很多优化措施,比如对小数组使用插入排序、合并时考虑已排序的序列以及优化的比较和移动过程等。这些细微的优化使得Timsort成为一种非常快速且高效的排序算法,在现代编程语言中得到广泛采用。
五、Python中的单例实现简单示例
要实现一个只需实例化一次的类,你可以使用设计模式中的单例模式。在Python中,有多种方式实现单例模式。下面给出两种常见的实现方式:
- 使用类变量:
class Singleton:_instance = Nonedef __new__(cls, *args, **kwargs):if cls._instance is None:cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)return cls._instance# 使用示例
singleton1 = Singleton()
singleton2 = Singleton()assert singleton1 is singleton2 # 检查singleton1和singleton2是否是同一个实例
在这个例子中,我们重写了__new__
方法,它是在创建实例之前被调用的特殊方法。__new__
方法确保只创建单例类的一个实例,并且后续尝试创建新实例时都返回第一个创建的实例。
- 使用装饰器:
def singleton(cls):instances = {}def get_instance(*args, **kwargs):if cls not in instances:instances[cls] = cls(*args, **kwargs)return instances[cls]return get_instance@singleton
class MySingleton:pass# 使用示例
singleton1 = MySingleton()
singleton2 = MySingleton()assert singleton1 is singleton2 # 检查singleton1和singleton2是否是同一个实例
在这个例子中,我们使用了一个装饰器singleton
,它接收一个类并返回一个函数get_instance
。这个函数检查该类是否已经有一个实例存在于字典instances
中,如果不存在就创建一个新的实例。如果已经存在,就返回那个实例。当你用@singleton
装饰一个类时,你实际上把这个类替换成了get_instance
函数。
两种方法都能够确保一个类在程序运行期间只有一个实例。选择哪种方式取决于你的具体需求和偏好。