文章目錄
- 一、工具
- 二、需求
- 三、簡單的使用例子
- 四、原理分析
- 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
函數。
兩種方法都能夠確保一個類在程序運行期間只有一個實例。選擇哪種方式取決于你的具體需求和偏好。