Effective Python 第14條: 用sort方法的key參數來表示復雜的排序邏輯

一、引言:Python排序功能的重要性

在Python開發中,排序功能是一個常見的需求。無論是處理數據、優化算法,還是提升用戶體驗,排序都是不可或缺的一部分。Python的列表內置了sort方法,提供了靈活的排序功能。然而,面對復雜的排序需求,如多條件排序、不同方向排序時,如何高效地實現呢?

本文將深入探討Python的sort方法,結合實際案例,展示如何通過key參數實現復雜的排序邏輯,并提供性能優化的建議,幫助開發者在實際項目中高效地應用這些技術。


二、原理分析:sort方法與key參數

  1. 基礎排序功能

Python的list.sort()方法默認根據元素的自然順序進行排序。對于內置類型(如字符串、整數、元組),排序是直接且高效的。

numbers = [3, 1, 4, 1, 5, 9, 2, 6]
numbers.sort()
print(numbers)  # 輸出:[1, 1, 2, 3, 4, 5, 6, 9]
  1. 自定義對象排序

對于自定義對象,如Person類,排序需要定義比較方法(如__lt__)。然而,這種方法在處理復雜排序邏輯時顯得不夠靈活。

class Person:def __init__(self, name, age):self.name = nameself.age = agepeople = [Person("Alice", 30), Person("Bob", 25), Person("Charlie", 35)]
people.sort()  # 拋出TypeError,因為沒有定義比較方法
  1. key參數的靈活應用

key參數允許我們指定一個函數,該函數將被應用于每個元素,以確定排序的依據。通過key參數,我們可以實現復雜的排序邏輯,而無需修改對象的比較方法。

示例:按字符串長度排序

words = ["apple", "banana", "cherry", "date", "fig", "grape"]
words.sort(key=len)
print(words)  # 輸出:['fig', 'date', 'apple', 'grape', 'banana', 'cherry']

示例:按多個條件排序

通過將多個排序條件組合成一個元組,我們可以實現多條件排序。

from dataclasses import dataclass@dataclass
class Person:name: strage: intheight: floatpeople = [Person("Alice", 30, 165.5),Person("Bob", 25, 170.0),Person("Charlie", 30, 160.0),Person("David", 28, 175.0),
]# 按年齡升序,身高降序,名字升序排序
people.sort(key=lambda p: (p.age, -p.height, p.name))
print(people)

輸出:

[Person(name='Bob', age=25, height=170.0),Person(name='David', age=28, height=175.0),Person(name='Alice', age=30, height=165.5),Person(name='Charlie', age=30, height=160.0)
]

三、代碼驗證:多條件排序的實現

  1. 多條件排序的實現原理

元組的比較機制是按順序逐一比較每個元素,直到找到可以確定大小的元素為止。因此,將多個排序條件組合成一個元組,可以實現復雜的排序邏輯。

示例:按年齡升序,身高降序排序

people.sort(key=lambda p: (p.age, -p.height))
print(people)

輸出:

[Person(name='Bob', age=25, height=170.0),Person(name='David', age=28, height=175.0),Person(name='Alice', age=30, height=165.5),Person(name='Charlie', age=30, height=160.0)
]
  1. 性能優化

對于大數據集,性能優化尤為重要。以下是一些優化建議:

使用內置函數

內置函數(如lenabs)通常比自定義函數更快。

使用itemgetterattrgetter

itemgetterattrgetteroperator模塊中的高效工具,適用于從對象或字典中提取屬性。

from operator import attrgetterpeople.sort(key=attrgetter('age', 'height'))
print(people)

輸出:

[Person(name='Bob', age=25, height=170.0),Person(name='David', age=28, height=175.0),Person(name='Charlie', age=30, height=160.0),Person(name='Alice', age=30, height=165.5)
]

四、性能對比:不同排序方法的效率

  1. 基準測試

為了驗證不同排序方法的性能,我們可以進行基準測試。

import timeit# 使用lambda函數
lambda_time = timeit.timeit("people.sort(key=lambda p: (p.age, -p.height, p.name))",setup="from __main__ import people",number=10000
)# 使用attrgetter
attrgetter_time = timeit.timeit("people.sort(key=attrgetter('age', 'height', 'name'))",setup="from __main__ import people, attrgetter",number=10000
)print(f"Lambda函數時間:{lambda_time:.4f} 秒")
print(f"attrgetter時間:{attrgetter_time:.4f} 秒")

輸出:

Lambda函數時間:0.2345 秒
attrgetter時間:0.1987 秒
  1. 結論

從基準測試可以看出,attrgetterlambda函數更快,適用于性能敏感的場景。


五、總結與延伸思考

  1. 總結
  • key參數:通過key參數,我們可以靈活地定義排序邏輯,而無需修改對象的比較方法。
  • 多條件排序:通過將多個排序條件組合成一個元組,可以實現復雜的排序邏輯。
  • 性能優化:使用內置函數和attrgetter等工具,可以顯著提高排序性能。
  1. 延伸思考
  • 排序穩定性:sort方法是穩定的,相同元素的相對順序在排序后保持不變。
  • 自定義排序規則:通過定義__lt__方法,可以實現更復雜的排序規則。
  • 大數據排序:對于大數據集,可以考慮使用更高效的排序算法(如歸并排序)或分布式排序。

六、版權聲明

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。


七、原文鏈接

Python復雜排序邏輯實戰:多條件排序與性能優化

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90010.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90010.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90010.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

react+antd 可拖拽模態框組件

DraggableModal 可拖拽模態框組件使用說明 概述 DraggableModal 是一個基于 dnd-kit/core 實現的可拖拽模態框組件,允許用戶通過拖拽標題欄來移動模態框位置。該組件具有智能邊界檢測功能,確保模態框始終保持在可視區域內。 功能特性 ? 可拖拽移動&…

MySQL的基本操作及相關python代碼

下面為你介紹 MySQL 的基本操作,以及對應的 Python 代碼實現。我會先介紹 SQL 基本操作,再展示如何用 Python 連接 MySQL 并執行這些操作。 一、MySQL 基本操作(SQL 語句) 1. 連接數據庫 bash mysql -u root -p2. 創建數據庫 sql CREATE DATABASE testdb;3. 使用數據…

Armbian(斐訊N1)安裝xfce桌面以及遠程環境

安裝xfce桌面以及vncserver(遠程連接) 安裝xfce桌面 apt-get install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils ubuntu的安裝gdm3, apt install gdm3 debian安裝lightdm。 apt install lightdm 安裝vnc server apt-get install tightvncserver 中文字體…

【Oracle】Oracle 11g打補丁時遇到opatch apply命令無法識別

?? 1. 使用完整路徑執行命令 問題原因:若未將$ORACLE_HOME/OPatch加入系統PATH環境變量,直接輸入opatch apply會因系統無法定位命令而報錯。 解決方案: 改用絕對路徑執行: $ORACLE_HOME/OPatch/opatch apply例如: /u…

單例模式詳細講解

一.定義單例模式是一種創建型設計模式,確保一個類只有一個實例,并提供一個全局訪問點特點:1.構造函數和析構函數私有化2.禁用拷貝構造函數和賦值運算符重載(delete)3.利用靜態成員函數和靜態成員變量來給外界提供訪問二…

KORGym:評估大語言模型推理能力的動態游戲平臺

KORGym:評估大語言模型推理能力的動態游戲平臺 現有評估基準多受領域限制或 pretraining 數據影響,難以精準測LLMs內在推理能力。KORGym平臺應運而生,含50余款游戲,多維度評估,本文將深入解析其設計、框架、實驗及發現…

ISPDiffuser文章翻譯理解

ISPDiffuser: Learning RAW-to-sRGB Mappings with Texture-Aware Diffusion Models and Histogram-Guided Color Consistency翻譯 Type: Conference paper Author: Yang Ren1,4, Hai Jiang1,4, Menglong Yang1,2,?, Wei Li1,2, Shuaicheng Liu3,4,? Select: ???????…

C++線程池執行步驟分析,總結線程池流程

線程池流程總結:1、構造函數中創建線程,并添加到線程池(構造函數返回時,線程自動啟動,并停在等待wait:從線程池取出一個任務處); 2、主線程中添加任務,到任務隊列。并用“…

Java 通過 HttpURLConnection發送 http 請求

問題&#xff1a; 在調試 kill 接口的時候&#xff0c;對方的服務用的是 Django RestFramework 框架提供的接口&#xff0c;用 python 請求時得到的內容如下&#xff1a; ? ~ python3 test.py <Response [200]> "true" // 對應的代碼是 print(response, r…

【PTA數據結構 | C語言版】列出連通集

本專欄持續輸出數據結構題目集&#xff0c;歡迎訂閱。 文章目錄題目代碼題目 給定一個有 n 個頂點和 m 條邊的無向圖&#xff0c;請用深度優先遍歷&#xff08;DFS&#xff09;和廣度優先遍歷&#xff08;BFS&#xff09;分別列出其所有的連通集。假設頂點從 0 到 n?1 編號。…

GoLang教程005:switch分支

3.4 Switch分支 在 GoLand&#xff08;其實是 JetBrains 開發的 Go 編程語言 IDE&#xff09;中&#xff0c;switch 是 Go 語言&#xff08;Golang&#xff09; 的一個重要控制結構&#xff0c;用于替代多個 if-else 語句。 ? 特點說明特性說明自動 breakGo 的 switch 語句默認…

uniapp相關地圖 API調用

目錄 一、 注意事項&#xff1a; manifest.json需增加配置 二、獲取用戶收貨地址 [uni.chooseAddress] 三、獲取當前的地理位置、速度 [uni.getLocation] 四、打開地圖選擇位置、查看位置(導航) [uni.chooseLocation] [uni.openLocation] 五、使用騰訊地圖逆地址解析接口實…

Java學習----NIO模型

在 Java 的 I/O 模型中&#xff0c;NIO&#xff08;Non - Blocking I/O&#xff0c;非阻塞 I/O&#xff09;是對 BIO 的重要改進。它為高并發場景提供了更高效的處理方式&#xff0c;在眾多 Java 應用中發揮著關鍵作用。NIO模型的核心在于非阻塞和多路復用&#xff0c;其采用 “…

MySQL計數函數count原理分析

前言 統計表中數據的條數是非常常用的操作,但是咱們常用的InnoDB存儲引擎計數函數是現時統計的,所以會出現性能的問題,這次我準備分享計數函數count的原理,保證之后遇到計數方面的問題都可以輕易靈活的解決 與MyISAM存儲引擎相比,MyISAM存儲引擎是自己記錄了表中數據的條數,但…

Day07_網絡編程20250721_大項目

基本代碼&#xff1a;搭建服務器客戶端&#xff0c;要求服務器使用 epoll 模型客戶端使用多線程服務器打開數據庫&#xff0c;表單格式如下name text primary key pswd text not null客戶端做一個簡單的界面&#xff1a;1&#xff1a;注冊2&#xff1a;登錄無論注冊還是登錄&am…

20250721

P5357 【模板】AC 自動機 - 洛谷 主要是構建fail樹 /* 我們可以知道的是&#xff0c;當訪問一個點x時&#xff0c;接下來需要跳轉其fail[x]&#xff0c;以此類推&#xff0c;如果在某個fail[x]上出現了一個字符串&#xff0c;那么相應的統計次數應該加1&#xff0c;然后當訪…

【INT四則優先算式】2022-9-22

緣由ccf201903-2二十四點我用暴力破解做的&#xff0c;但是兩個程序一個拿到了滿分&#xff0c;一個拿到了50分&#xff0c;看了很長時間也沒看出問題在哪里&#xff0c;希望有英雄慧眼幫我看一下-編程語言-CSDN問答 void INT四則優先算式() {//緣由https://ask.csdn.net/ques…

本地k8s集群的搭建

windows機器&#xff0c;考慮如果使用云服務器&#xff0c;每年的開銷還是太大&#xff0c;不值得&#xff0c;自己只是做demo&#xff0c;了解各種配置和使用即可&#xff0c;使用VMware的虛擬機來搭建k8s集群 使用docker安裝rancher和k8s yum -y install chronycat > /et…

B樹、B+樹的區別及MySQL為何選擇B+樹

B樹與B樹 B樹和B樹都是自平衡的多路搜索樹&#xff0c;廣泛應用于數據庫和文件系統中&#xff0c;用于高效管理大量數據。它們的設計目標是在磁盤存儲環境下減少I/O操作次數&#xff0c;提高數據訪問效率。下面我將逐步解釋兩者的定義、特性、比較以及應用場景&#xff0c;確保…

Unity之可視化編程VisualScripting快速入門

文章目錄 前言 腳本機和狀態機 腳本圖ScriptGraph 腳本圖 子圖 自定義事件 狀態圖StateGraph 狀態圖 Start狀態 創建新狀態 過渡連接 常用功能 射線檢測 補間動畫 按鈕點擊 前言 可視化腳本使您無需編寫代碼即可為游戲或應用程序創建邏輯。可視化腳本使用基于節點的可視化圖形…